java - executorService.submit(Runnable) 返回的 future 对象是否包含对可运行对象的任何引用?

标签 java runnable future executorservice

假设我们有以下代码:

List<Future<?>> runningTasks;
ExecutorService executor;
...
void executeTask(Runnable task){
    runningTasks.add(executor.submit(task));
}

我的问题是:

  1. runningTasks 是否包含对 task 对象的引用?
  2. 它能保持多长时间?任务完成后它还持有吗?
  3. 为了避免内存泄漏,我是否必须小心删除添加到列表中的 future ?

最佳答案

直到执行者或 Future 对象持有对它的引用时是一个实现细节。因此,如果您的任务使用大量内存以至于您不得不担心内存使用,您应该在任务完成之前在任务中明确清理。

如果你看OpenJDK 1.6 source codeThreadPoolExecutor 中,您可以看到实际上底层 Future 对象实际上无限期地保留对底层可调用对象的引用(即只要存在对 的强引用code>Future 对象,可调用对象不能是 GCd)。 1.7 也是如此。从 1.8 开始,对它的引用取消了。但是,您无法控制您的任务将在 ExecutorService 的哪个实现上运行。

使用 WeakReference 应该在实践中作为 Future 工作,因此一旦任务完成并且理智的实现,Callable 对象就可以被 GCd当任务完成时,ExecutorService 应该失去对它的引用。严格来说,这仍然取决于 ExecutorService 的实现。此外,使用 Wea​​kReference 会增加惊人的开销。你最好直接明确地清理任何占用大量内存的对象。相反,如果您不分配大对象,那么我就不会担心。

当然,这个讨论与如果您不断向列表中添加 future 而不删除任何 future 会遇到的内存泄漏完全不同。如果您这样做,即使使用 WeakReference 也无济于事;你仍然会有内存泄漏。为此,只需遍历列表并删除已经完成因此没有用的 future 。每次都这样做真的很好,除非你有一个大得离谱的队列,因为这是非常快的。

关于java - executorService.submit(Runnable) 返回的 future 对象是否包含对可运行对象的任何引用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23014606/

相关文章:

regex - 使用 scala future 的大文件的多个并行 grep 没有所需的速度

java - 使用 RequestFuture.get() 时 Android Volley 超时异常

java - 如何在我的 java 应用程序中对 Google OAuth 的 client_id 和 client_secret 进行硬编码?

java - 有没有办法让 selenium 存储 cookie,以便我可以在 java 代码中调用它?

android - 如何将 Toast 放入服务的 Runnable 中?

java - 安排常规任务而不扩展TimerTask?

Java 线程池执行器

firebase - Future<int> 无法从 Firebase 获取数据

java - Java 中的正则表达式和字符串数组

java - 抑制小写 'log' 字段的 PMD VariableNamingConventions 规则