Thread 内存泄露

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

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


 <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 savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new MyThread().start();
} private class MyThread extends Thread {
@Override
public void run() {
super.run();
dosomthing();
}
}
private void dosomthing(){ }
}


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


真的没有问题吗

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

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

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

    
    
    <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);
    } @Override
    public void run() {
    super.run();
    if (mThreadActivityRef == null)
    return;
    if (mThreadActivityRef.get() != null)
    mThreadActivityRef.get().dosomthing();
    // dosomthing
    }
    }
    }

    
    

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

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

3.AsynTask 内部类会怎样呢?

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

代码例如以下:

/**
*
* 弱引用
* @version 1.0.0
* @author Abay Zhuang <br/>
* Create at 2014-7-17
*/
public abstract class WeakAsyncTask<Params, Progress, Result, WeakTarget>
extends AsyncTask<Params, Progress, Result> {
protected WeakReference<WeakTarget> mTarget; public WeakAsyncTask(WeakTarget target) {
mTarget = new WeakReference<WeakTarget>(target);
} @Override
protected final void onPreExecute() {
final WeakTarget target = mTarget.get();
if (target != null) {
this.onPreExecute(target);
}
} @Override
protected final Result doInBackground(Params... params) {
final WeakTarget target = mTarget.get();
if (target != null) {
return this.doInBackground(target, params);
} else {
return null;
}
} @Override
protected 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); protected void onPostExecute(WeakTarget target, Result result) {
// Nodefaultaction
}
}

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. 如何用SVG写一个环形进度条以及动画

    本次案例主要使用了svg的三个元素,分别为circle.text.path,关于svg的介绍大家可以看MDN上的相关教程,传送门 由于svg可以写到HTML中,所以这里我们就可以很方便的做进度条加载动 ...

  2. C# 数组动态添加新元素的 方法

    经常在开发中  会对字符串 进行split 拆分操作.. 得到数组后再去做相应的事情! 但有时候,需求决定了 数组的长度 不是固定的, 而C# 数组 是不允许动态添加新的元素的.. 这事情让我也纠结了 ...

  3. B - Ultra-Fast Mathematician

    Problem description Shapur was an extremely gifted student. He was great at everything including Com ...

  4. 由于找不到 opencv_world320.dll,无法继续执行代码

    首先找到自己软件安装(解压)的路径openCV (安装(解压)目录\opencv\build\x64\vc14\bin) 我的安装(解压)目录是:F:\OpenCV\Three320\opencv\b ...

  5. CSS简单入门

    - Java攻城狮学习路线 - 一. 什么是CSS CSS指层叠样式表(Cascading Style Sheets),定义如何显示HTML元素 二. CSS语法 /* 选择器 { 声明: 声明:}* ...

  6. 第八周读书笔记(人月神话X月亮与六便士)——到底什么才是一个程序员的自我修养?

    写了这么久的读书笔记,涉及到问题大多是一些如何把软件工程做好,如何把自己的职业生涯做好.但总感觉逻辑链上缺了一环,亦即:我们为什么要把软件工程做好,我们成为一名优秀的职业生涯的意义到底在于什么?我觉得 ...

  7. C语言运算符类型

    算术运算符 运算符 描述 + 两个操作数相加 - 第一操作数减去第二个操作数 * 两个操作数相乘 / 分子除以分母 % 模运算和整数除法后的余数 ++ 递增操作增加一个整数值 -- 递减操作减少一个整 ...

  8. JDBCUtils 工具类

    import com.alibaba.druid.pool.DruidDataSourceFactory; import javax.sql.DataSource;import java.io.IOE ...

  9. location.reload() 和 location.replace()的区别和应用。

    首先介绍两个方法的语法: reload 方法,该方法强迫浏览器刷新当前页面.语法:location.reload([bForceGet])  参数:bForceGet, 可选参数, 默认为 false ...

  10. 【leecode】独特的电子邮件地址

    每封电子邮件都由一个本地名称和一个域名组成,以 @ 符号分隔. 例如,在 alice@leetcode.com中, alice 是本地名称,而 leetcode.com 是域名. 除了小写字母,这些电 ...