Thread Memory leak
线程也是造成内存泄露的一个重要的源头。线程产生内存泄露的主要原因在于线程生命周期的不可控。
1. See if there is a problem
<span style=" White-space:pre "></span>/** * * @version 1.0.0 * @author Abay Zhuang <br /> * Create at 2014-7-17 */public class Threadactivity extends Activity {public void onCreate (Bundle savedinstancesta TE) {super.oncreate (savedinstancestate); Setcontentview (R.layout.activity_main); new MyThread (). Start (); Private class MyThread extends Thread {@Overridepublic void run () {Super.run ();d osomthing ();}} private void Dosomthing () {}}
This code is very common and simple, it is the form that we often use.
Is there really no problem?
我们思考一个问题:假设MyThread的run函数是一个很费时的操作,当我们开启该线程后,将设备的横屏变为了竖屏,一般情况下当屏幕转换时会重新创建Activity,按照我们的想法,老的Activity应该会被销毁才对,然而事实上并非如此。由于我们的线程是Activity的内部类,所以MyThread中保存了Activity的一个引用,当MyThread的run函数没有结束时,MyThread是不会被销毁的,因此它所引用的老的Activity也不会被销毁,因此就出现了内存泄露的问题。
2. What should be done to solve the memory leak problem caused by this thread?
- First, the internal class of the thread is changed to a static inner class.
Second, use weak references inside the thread to save the context reference. The code is as follows:
<span style= "White-space:pre" ></span>/** * * @version 1.0.0 * @author Abay Zhuang <br/> * Create at 2014-7-17 */public class Threadavoidactivity extends Activity {public void onCreate (Bundle savedinstancestate) { Super.oncreate (savedinstancestate); Setcontentview (R.layout.activity_main); new MyThread (This). Start (); private void Dosomthing () {}private static class MyThread extends Thread {weakreference<threadavoidactivity> Mthreadactivityref;public MyThread (threadavoidactivity activity) {mthreadactivityref = new weakreference< Threadavoidactivity> (activity);} @Overridepublic void Run () {super.run (); if (mthreadactivityref = = null) return;if (mthreadactivityref.get () = null) Mthreadactivityref.get (). dosomthing ();//Dosomthing}}}
The above two steps are actually a two-way strong reference link to toggle two objects
- Static inner class: Cut off the activity's strong reference to Mythread.
- Weak references: Cut off Mythread's strong references to activity.
What happens to the 3.AsynTask inner class?
有些人喜欢用Android提供的AsyncTask,但事实上AsyncTask的问题更加严重,Thread只有在run函数不结束时才出现这种内存泄露问题,然而AsyncTask内部的实现机制是运用了ThreadPoolExcutor,该类产生的Thread对象的生命周期是不确定的,是应用程序无法控制的,因此如果AsyncTask作为Activity的内部类,就更容易出现内存泄露的问题。
The code is as follows:
/** * * Weak citation * @version 1.0.0 * @author Abay Zhuang <br/> * Create at 2014-7-17 */public abstract class Wea Kasynctask<params, Progress, Result, weaktarget> extends Asynctask<params, Progress, result> {protected Wea Kreference<weaktarget> mtarget;public Weakasynctask (weaktarget target) {mtarget = new Weakreference<weaktarg Et> (target);} @Overrideprotected final void OnPreExecute () {final Weaktarget target = Mtarget.get (); if (target! = null) {This.onpreexecute (target); }} @Overrideprotected final Result doinbackground (params ... params) {final Weaktarget target = Mtarget.get (); if (target! = null) {return This.doinbackground (target, params); } else {return null; }} @Overrideprotected final void OnPostExecute (result result) {final Weaktarget target = Mtarget.get (); if (target! = null) {This.onpostexecute (target, result); }}protected void OnPreExecute (Weaktarget target) {//Nodefaultaction}protected abstract Result doinbackground (weaktarget target, params ... params);p rotected void OnPostExecute (weaktarget target, result result) {//Nodefaultaction}}