Activity已销毁,创建的线程未回收问题
2017-10-09 09:47
411 查看
今天在做新模块测试时发现了一个严重的问题,当一个activity开启一个线程时,如果当前activity调用finish()函数不会关闭当前创建的线程。对于每个新建activity,如果activity中的线程发生内存泄漏。在Java中线程时垃圾回收机制的根源,也就是说,在运行系统中DVM虚拟机总会使硬件持有运行状态的进程的引用,结果导致处于运行状态的线程将永远不会回收。因此你必须为你的后台线程实现销毁逻辑。
先说下问题出现的场景,我在一个activity中创建一个线程,轮询去发送请求,正常情况下是没什么问题的,先看下问题代码:
这时看Log日志是正常打印,然后我按返回键退出当前应用,发现Log日志还在打印,问题出现了,线程被没有被回收,而且当你再次返回到应用时,会再在后台创建一个线程,两个线程同时在跑。
![](http://img.blog.csdn.net/20170210143040075?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYzY2NDU0MzMzMA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
在Java中强制关闭线程是非安全性操作,这时我们要为自己的线程添加判断条件,相关代码如下:
这样,当activity销毁时走destroy函数然后调用Thread的close,让线程退出轮询,保证了线程安全回收。
还有另外一个思路来让线程可以及时回收,我们知道context对象与activity是绑定的,我们可以实例application来暂存当前context与当前context进行比较,我们可以优化上面的代码,具体代码如下:
自定义application用来暂存context对象:
让线程去做context比较,这样我们就可以忽略activity的生命周期:
大功告成。
先说下问题出现的场景,我在一个activity中创建一个线程,轮询去发送请求,正常情况下是没什么问题的,先看下问题代码:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); new Thread(new Runnable() { @Override public void run() { while (1 == 1) { try { Thread.sleep(1000); Log.i("-------", "running"); } catch (InterruptedException e) { e.printStackTrace(); } } } }).start(); }
这时看Log日志是正常打印,然后我按返回键退出当前应用,发现Log日志还在打印,问题出现了,线程被没有被回收,而且当你再次返回到应用时,会再在后台创建一个线程,两个线程同时在跑。
在Java中强制关闭线程是非安全性操作,这时我们要为自己的线程添加判断条件,相关代码如下:
private MyThread myThread; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); myThread = new MyThread(); myThread.start(); } private class MyThread extends Thread { private boolean stop = false; @Override public void run() { super.run(); while (!stop) { try { Thread.sleep(1000); Log.i("-------", "running"); } catch (InterruptedException e) { e.printStackTrace(); } } } public void close() { stop = true; } } @Override protected void onDestroy() { super.onDestroy(); myThread.close(); }
这样,当activity销毁时走destroy函数然后调用Thread的close,让线程退出轮询,保证了线程安全回收。
还有另外一个思路来让线程可以及时回收,我们知道context对象与activity是绑定的,我们可以实例application来暂存当前context与当前context进行比较,我们可以优化上面的代码,具体代码如下:
自定义application用来暂存context对象:
public class MyApplication extends Application { static Context appContext; @Override public void onCreate() { super.onCreate(); } public static void setContext(Context context) { appContext = context; } }
让线程去做context比较,这样我们就可以忽略activity的生命周期:
private MyThread myThread; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); MyApplication.setContext(this); myThread = new MyThread(this); myThread.start(); } private class MyThread extends Thread { private boolean stop = false; private Context context; public MyThread(Context context) { this.context = context; } @Override public void run() { super.run(); while (context == MyApplication.appContext) { try { Thread.sleep(1000); Log.i("-------", "running"); } catch (InterruptedException e) { e.printStackTrace(); } } } }
大功告成。
相关文章推荐
- Activity已销毁,创建的线程未回收问题
- 线程创建未回收导致的内存泄漏问题(进程中的堆栈内存,并不是malloc出来的内存)
- Activity已经销毁了,线程还在运行的问题
- Android Activity 销毁后线程会不会被GC回收?
- Activity非正常销毁后重新创建问题
- Activity已经销毁了,线程还在运行的问题
- linux创建线程时,需注意线程内存回收问题!
- Android开发——异步任务中Activity销毁时的问题
- 线程创建的函数选择问题
- 线程创建后不执行问题
- 处理activity销毁的问题
- 答疑学员关于垃圾回收线程安全问题…
- 关于调用系统照相机等,onActivityResult之后Activity被销毁问题解决
- 内核层监控进程 线程 创建和销毁
- 创建指定大小,当空闲超时还会自动销毁线程的线程池
- 【进程线程与同步】5.1 创建和销毁子进程
- 创建线程的两种方法和同步线程的问题
- 黑马程序员-解决系统报错“线程间操作无效: 从不是创建控件" txtbox1" 的线程访问它”问题的方法
- Activity被回收后,重建时Fragment重叠问题
- 线程间操作无效: 从不是创建控件“Control Name'”的线程访问它问题的解决方案及原理分析