2013-11-22 22 views
1

我写了一些代码,我可能需要创建一个无限数量的未来对象(java.util.concurrent.Future)。Java并发:是否取消他们需要收集垃圾的期货?

但是我担心在某个时候内存不足。

问题的夫妇在这里:

  1. 是否JVM知道,一旦未来已经完成,它没有被任何地方refernced,因此可享有GC(即使在其中创建它的线程仍然活着和跑步)?
  2. 理想情况下,我不想跟踪这些期货本身。但是,如果我确实保留这些期货的参考资料并定期对它们进行取消,那么它们是否可以用于GC?

回答

3

您需要最终删除对Future的任何引用,以便它们被垃圾收集。通常的做法是维护Future的集合并定期检查isDone()是否返回true。如果是这样,任务已完成并且可能会清除对其的引用。如果您担心堆积一些可能安全中断的长时间运行的任务,则需要拨打Future上的cancel()并删除/清空可能存在的任何对其的引用。

一般来说,构建一个可能会遇到无限增长的系统总是一个坏主意。如果未完成Future对象的数量变得太大,则应在系统中的其他位置应用反压。

未必一定是“一旦未来完成,它就不会被引用到任何地方”。例如,参考它的客户可以在任何时候通过get()方法请求结果。因此,JVM需要保留Future直到所有这些外部引用都被删除。当Future“完成”(即完成其任务或被取消)时,线程池中的引用将被删除。

+0

谢谢!并且ExecutorService被传递给我的代码,并通过在该ExecutorService上调用submit()来创建期货。该执行者服务即使完成,仍将继续参照期货。我不认为有办法告诉executorService清除已完成的期货:(。 –

+0

)ExecutorService将一直完成时不会持有通过submit()提交的任务的引用。如果在运行程序中有其他地方提到'Future',可以关注这个问题 –

+0

Thanks @ andrew-bissell! –

0

你见过this的问题吗?

未来的计算完成后,您无法再取消它。 我不知道确切的上下文,但有一个建议是跟踪期货,取消你想要的或者需要取消的,并且呼叫清除执行者将他们从工作队列中移除。

希望它有帮助。

+0

感谢您指出这一点。但是,我使用的是executorService而不是ThreadPoolExecutor。而ExecutorService似乎没有'purge()'方法。 –