【问题标题】:Anonymous runnable and memory leak匿名可运行和内存泄漏
【发布时间】:2015-06-13 11:35:19
【问题描述】:

假设我们在某个静态类中有一个静态方法,它在单独的线程中运行一些操作(有一个可运行的)并通过某个侦听器返回结果:

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);
            }
        });
    }
}
}

在其他类中我们调用方法getSomeData():

public class SomeOtherClass {
private Object mResult;

public void someMethod(){

   SomeStaticClass.getSomeData(new IDataLoadCompleteListener(){

     @Override
     public void onDataLoadComplete(final Object result) {
        mResult = result;
     }

   });

}

}

所以在这种情况下,我想知道在 mExecService 中创建的匿名可运行文件何时可用于垃圾收集?这个 sn-p 是否存在一些内存泄漏问题?在我看来,这个匿名可运行对象将存在很长时间,直到 SomeOtherClass 或其字段 mResult 被垃圾回收,因为我们在可运行对象中创建了一个对象并在侦听器中通过引用传递,对吗?

【问题讨论】:

  • runnable 引用了 someOtherClass;但不是相反。
  • 一旦 Runnable 完成了它的动作,如何到达它?对象不关心它是在哪里创建的,例如在可运行对象中创建的对象。重要的是对象是否可达,如果不可达,是否有资格进行垃圾回收。

标签: java runnable anonymous-class


【解决方案1】:

匿名类内存泄漏的问题正好相反。您创建的IDataLoadCompleteListener 隐式引用了外部类实例:在您的情况下为SomeOtherClass。因此,SomeOtherClass 实例在收集到侦听器之前不能被垃圾收集。但在你的情况下似乎没问题。至于Runnable,则不存在这样的问题,因为它是在static方法内部创建的。因此,在您的Runnable 执行后,它将与匿名侦听器一起符合 GC 条件。在您的情况下不会产生内存泄漏。

【讨论】:

    【解决方案2】:

    挖掘了一些java源代码。线程存储在ThreadPoolExecutor 中的私有Worker 类中。只要没有完成,所有工作人员都存储在地图中。完成或终止后,它们将从地图中删除。 Worker 以及扩展的 ThreadRunnable 都是垃圾,将被回收。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-01-17
      • 2017-01-06
      • 2015-12-28
      • 1970-01-01
      • 2017-01-31
      • 1970-01-01
      • 2012-02-20
      • 1970-01-01
      相关资源
      最近更新 更多