匿名可运行和内存泄漏
Anonymous runnable and memory leak
假设我们在一些静态 class 中有一些静态方法,它在单独的线程中运行一些操作(有一个可运行的)并且 returns 一些监听器的结果:
public class SomeStaticClass {
private static ExecutorService mExecService = Executors.newCachedThreadPool();
........
public interface IDataLoadCompleteListener {
public void onDataLoadComplete(Object result);
}
........
public static void getSomeData(final IDataLoadCompleteListener listener) {
if (listener != null) {
mExecService.execute(new Runnable() {
@Override
public void run() {
........
do something
........
Object result = new Object();
listener.onDataLoadComplete(result);
}
});
}
}
}
在其他 class 中我们调用方法 getSomeData():
public class SomeOtherClass {
private Object mResult;
public void someMethod(){
SomeStaticClass.getSomeData(new IDataLoadCompleteListener(){
@Override
public void onDataLoadComplete(final Object result) {
mResult = result;
}
});
}
}
所以在这种情况下,我想知道在 mExecService 中创建的匿名可运行对象何时可用于垃圾收集?此代码段中是否存在内存泄漏问题?在我看来,这个匿名 runnable 将存在很长时间,直到 SomeOtherClass 或其字段 mResult 被垃圾收集,因为我们在 runnable 中创建了一个对象并在 listener 中按引用传递,对吗?
浏览了一些 java 源代码。线程存储在私有Worker
class中ThreadPoolExecutor
。所有的worker只要没有完成,都存储在一个map中。完成或终止后,它们将从地图中移除。 Worker
,以及 Thread
和 Runnable
都是垃圾,将被捡起。
匿名classes内存泄漏的问题正好相反。您创建的 IDataLoadCompleteListener
具有对外部 class 实例的隐式引用:在您的情况下为 SomeOtherClass
。因此 SomeOtherClass
实例在收集侦听器之前不能被垃圾收集。但在你的情况下似乎没问题。至于Runnable
,则没有这个问题,因为它是在static
方法内部创建的。因此,在您的 Runnable
执行后,它将有资格与匿名侦听器一起进行 GC。在您的案例中没有产生内存泄漏。
假设我们在一些静态 class 中有一些静态方法,它在单独的线程中运行一些操作(有一个可运行的)并且 returns 一些监听器的结果:
public class SomeStaticClass {
private static ExecutorService mExecService = Executors.newCachedThreadPool();
........
public interface IDataLoadCompleteListener {
public void onDataLoadComplete(Object result);
}
........
public static void getSomeData(final IDataLoadCompleteListener listener) {
if (listener != null) {
mExecService.execute(new Runnable() {
@Override
public void run() {
........
do something
........
Object result = new Object();
listener.onDataLoadComplete(result);
}
});
}
}
}
在其他 class 中我们调用方法 getSomeData():
public class SomeOtherClass {
private Object mResult;
public void someMethod(){
SomeStaticClass.getSomeData(new IDataLoadCompleteListener(){
@Override
public void onDataLoadComplete(final Object result) {
mResult = result;
}
});
}
}
所以在这种情况下,我想知道在 mExecService 中创建的匿名可运行对象何时可用于垃圾收集?此代码段中是否存在内存泄漏问题?在我看来,这个匿名 runnable 将存在很长时间,直到 SomeOtherClass 或其字段 mResult 被垃圾收集,因为我们在 runnable 中创建了一个对象并在 listener 中按引用传递,对吗?
浏览了一些 java 源代码。线程存储在私有Worker
class中ThreadPoolExecutor
。所有的worker只要没有完成,都存储在一个map中。完成或终止后,它们将从地图中移除。 Worker
,以及 Thread
和 Runnable
都是垃圾,将被捡起。
匿名classes内存泄漏的问题正好相反。您创建的 IDataLoadCompleteListener
具有对外部 class 实例的隐式引用:在您的情况下为 SomeOtherClass
。因此 SomeOtherClass
实例在收集侦听器之前不能被垃圾收集。但在你的情况下似乎没问题。至于Runnable
,则没有这个问题,因为它是在static
方法内部创建的。因此,在您的 Runnable
执行后,它将有资格与匿名侦听器一起进行 GC。在您的案例中没有产生内存泄漏。