Thread 内存泄露

  1. 线程也是造成内存泄露的一个重要的源头。线程产生内存泄露的主要原因在于线程生命周期的不可控。

1.看一下以下是否存在问题

  1.  <span style="white-space:pre">	</span>/**
  2. 	 *
  3. 	 * @version 1.0.0
  4. 	 * @author Abay Zhuang <br/>
  5. 	 *		   Create at 2014-7-17
  6. 	 */
  7. 	public class ThreadActivity extends Activity {
  8. 		public void onCreate(Bundle savedInstanceState) {
  9. 			super.onCreate(savedInstanceState);
  10. 			setContentView(R.layout.activity_main);
  11. 			new MyThread().start();
  12. 		}
  13. 		private class MyThread extends Thread {
  14. 			@Override
  15. 			public void run() {
  16. 				super.run();
  17. 				dosomthing();
  18. 			}
  19. 		}
  20. 		private void dosomthing(){
  21. 		}
  22. 	}
  1.  

这段代码非常寻常也非常easy,是我们常常使用的形式。

  1.  

真的没有问题吗

  1. 我们思考一个问题:如果MyThreadrun函数是一个非常费时的操作,当我们开启该线程后,将设备的横屏变为了竖屏。
  2. 普通情况下当屏幕转换时会又一次创建Activity,依照我们的想法。老的Activity应该会被销毁才对,然而其实并不是如此。
  3. 因为我们的线程是Activity的内部类。所以MyThread中保存了Activity的一个引用,当MyThreadrun函数没有结束时,
  4. MyThread是不会被销毁的。因此它所引用的老的Activity也不会被销毁。因此就出现了内存泄露的问题。

2.这样的线程导致的内存泄露问题应该怎样解决呢?

  • 第一、将线程的内部类,改为静态内部类。
  • 第二、在线程内部採用弱引用保存Context引用。 代码例如以下:

    1. <span style="white-space:pre">		</span>/**
    2. 		 *
    3. 		 * @version 1.0.0
    4. 		 * @author Abay Zhuang <br/>
    5. 		 *         Create at 2014-7-17
    6. 		 */
    7. 		public class ThreadAvoidActivity extends Activity {
    8. 			public void onCreate(Bundle savedInstanceState) {
    9. 				super.onCreate(savedInstanceState);
    10. 				setContentView(R.layout.activity_main);
    11. 				new MyThread(this).start();
    12. 			}
    13. 			private void dosomthing() {
    14. 			}
    15. 			private static class MyThread extends Thread {
    16. 				WeakReference<ThreadAvoidActivity> mThreadActivityRef;
    17. 				public MyThread(ThreadAvoidActivity activity) {
    18. 					mThreadActivityRef = new WeakReference<ThreadAvoidActivity>(
    19. 							activity);
    20. 				}
    21. 				@Override
    22. 				public void run() {
    23. 					super.run();
    24. 					if (mThreadActivityRef == null)
    25. 						return;
    26. 					if (mThreadActivityRef.get() != null)
    27. 						mThreadActivityRef.get().dosomthing();
    28. 					// dosomthing
    29. 				}
    30. 			}
    31. 		}
    1.  
    1.  

上面的两个步骤事实上是切换两个对象的双向强引用链接

  1. 静态内部类:切断Activity 对于 MyThread的强引用。
  2. 弱引用: 切断MyThread对于Activity 的强引用。

3.AsynTask 内部类会怎样呢?

  1. 有些人喜欢用Android提供的AsyncTask。但其实AsyncTask的问题更加严重,
  2. Thread仅仅有在run函数不结束时才出现这样的内存泄露问题,然而AsyncTask内部的实现机制是运用了ThreadPoolExcutor,
  3. 该类产生的Thread对象的生命周期是不确定的。是应用程序无法控制的。
  4. 因此假设AsyncTask作为Activity的内部类,就更easy出现内存泄露的问题。

代码例如以下:

  1. /**
  2.  *
  3.  * 弱引用
  4.  * @version 1.0.0
  5.  * @author Abay Zhuang <br/>
  6.  *         Create at 2014-7-17
  7.  */
  8. public abstract class WeakAsyncTask<Params, Progress, Result, WeakTarget>
  9.     extends AsyncTask<Params, Progress, Result> {
  10. protected WeakReference<WeakTarget> mTarget;
  11. public WeakAsyncTask(WeakTarget target) {
  12.     mTarget = new WeakReference<WeakTarget>(target);
  13. }
  14. @Override
  15. protected final void onPreExecute() {
  16.     final WeakTarget target = mTarget.get();
  17.     if (target != null) {
  18.         this.onPreExecute(target);
  19.     }
  20. }
  21. @Override
  22. protected final Result doInBackground(Params... params) {
  23.     final WeakTarget target = mTarget.get();
  24.     if (target != null) {
  25.         return this.doInBackground(target, params);
  26.     } else {
  27.         return null;
  28.     }
  29. }
  30. @Override
  31. protected final void onPostExecute(Result result) {
  32.     final WeakTarget target = mTarget.get();
  33.     if (target != null) {
  34.         this.onPostExecute(target, result);
  35.     }
  36. }
  37. protected void onPreExecute(WeakTarget target) {
  38.     // Nodefaultaction
  39. }
  40. protected abstract Result doInBackground(WeakTarget target,
  41.         Params... params);
  42. protected void onPostExecute(WeakTarget target, Result result) {
  43.     // Nodefaultaction
  44. }
  45. }

Android App 内存泄露之Thread的更多相关文章

  1. Android App 内存泄露之调试工具(1)

    Android App 内存泄露之工具(1) 使用内存监測工具 DDMS –> Heap 操作步骤 启动eclipse后,切换到DDMS透视图,并确认Devices视图.Heap视图都是打开的, ...

  2. Android App 内存泄漏Handler

    Android App 内存泄露之Handler Handler也是造成内存泄露的一个重要的源头,主要Handler属于TLS(Thread Local Storage)变量,生命周期和Activit ...

  3. Android 的内存泄露和内存限制

    转载自 https://blog.csdn.net/goodlixueyong/article/details/40716779 https://blog.csdn.net/vshuang/artic ...

  4. Android 常见内存泄露 & 解决方案

    前言 内存泄漏(Memory Leak)是指程序中己动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃 (OOM) 等严重后果. 那什么情况下不能被 ...

  5. Android 防内存泄露handler

    Android 防内存泄露handler 1.使用弱引用 WeakRefHander /** * 作者: allen on 15/11/24.感谢开源作者https://coding.net/u/co ...

  6. Android常见内存泄露,学会这六招优化APP性能

    很多开发者都知道,在面试的时候会经常被问到内存泄露和内存溢出的问题. 1.内存溢出(Out Of Memory,简称 OOM),通俗理解就是内存不够,即内存占用超出内存的空间大小. 2.内存泄漏(Me ...

  7. Android之内存泄露、内存溢出、内存抖动分析

      内存   JAVA是在JVM所虚拟出的内存环境中运行的,内存分为三个区:堆.栈和方法区.栈(stack):是简单的数据结构,程序运行时系统自动分配,使用完毕后自动释放.优点:速度快.堆(heap) ...

  8. Android中内存泄露与如何有效避免OOM总结

    一.关于OOM与内存泄露的概念 我们在Android开发过程中经常会遇到OOM的错误,这是因为我们在APP中没有考虑dalvik虚拟机内存消耗的问题. 1.什么是OOM OOM:即OutOfMemoe ...

  9. 关于Android 的内存泄露及分析

    一. Android的内存机制Android的程序由Java语言编写,所以Android的内存管理与Java的内存管理相似.程序员通过new为对象分配内存,所有对象在java堆内分配空间:然而对象的释 ...

随机推荐

  1. js slider

      <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.or ...

  2. springsecurity+jwt实践和学习

    1.参考资料: https://blog.csdn.net/qq924862077/article/details/83038031 https://blog.csdn.net/sxdtzhaoxin ...

  3. 原生js做h5小游戏之打砖块

    前言 首先,先说明一下做这个系列的目的:其实主要源于博主希望熟练使用 canvas 的相关 api ,同时对小游戏的实现逻辑比较感兴趣,所以希望通过这一系列的小游戏来提升自身编程能力:关于 es6 语 ...

  4. MAVEN学习笔记之私服Nexus(2)

    MAVEN学习笔记之私服Nexus(2) 私有服务器搭建 Nexus www.snatype.org下载 snatype-work 是默认nexus存储nexus a:将bin添加到环境中 Admin ...

  5. 八叉树(Octree)Typescript 实现

    Demo GitHub export class Octree { // 父&子树 private parent_node: any; private children_nodes: Octr ...

  6. 错误:Camera录制视频(6.0错误),5.1正常,7.1正常 (java.lang.RuntimeException: start failed.at android.media.MediaRecorder.native_start(Native Method))

    Process: com.example.mycamera2, PID: 24086 java.lang.RuntimeException: start failed. at android.medi ...

  7. 【Oracle】RAC控制文件多路复用

    1.—关闭数据库,各个节点都要关闭: [oracle@rac1 ~]$ srvctl stop database -d racdb -o immediate 2.—启动任一节点到nomount状态: ...

  8. 【Oracle】恢复丢失的临时表空间文件

    Oracle 11g以后,临时表空间文件是可以在重启数据库以后自动生成的(当然也可以在相同目录再建一个临时表空间文件),模拟实验如下: 1)删除临时表空间数据文件 SYS@ENMOEDU> se ...

  9. vc++如何创建程序01

    1 .选择文件+新建(ctrl+N),然后选择一个空的工程,完成 2 然后在选择file新建,在files文件下面选择一个C++Source File,并取个文件名(比如为point可以不带.c) 我 ...

  10. centos7编译安装mysql5.6

    先安装如下依赖包: $ yum -y install make gcc-c++ cmake bison-devel  ncurses-devel 下载MySQL5.6.14安装包,https://pa ...