我写了一些代码,我可能需要创建一个无限数量的未来对象(java.util.concurrent.Future)。Java并发:是否取消他们需要收集垃圾的期货?
但是我担心在某个时候内存不足。
问题的夫妇在这里:
- 是否JVM知道,一旦未来已经完成,它没有被任何地方refernced,因此可享有GC(即使在其中创建它的线程仍然活着和跑步)?
- 理想情况下,我不想跟踪这些期货本身。但是,如果我确实保留这些期货的参考资料并定期对它们进行取消,那么它们是否可以用于GC?
我写了一些代码,我可能需要创建一个无限数量的未来对象(java.util.concurrent.Future)。Java并发:是否取消他们需要收集垃圾的期货?
但是我担心在某个时候内存不足。
问题的夫妇在这里:
您需要最终删除对Future
的任何引用,以便它们被垃圾收集。通常的做法是维护Future
的集合并定期检查isDone()
是否返回true
。如果是这样,任务已完成并且可能会清除对其的引用。如果您担心堆积一些可能安全中断的长时间运行的任务,则需要拨打Future
上的cancel()
并删除/清空可能存在的任何对其的引用。
一般来说,构建一个可能会遇到无限增长的系统总是一个坏主意。如果未完成Future
对象的数量变得太大,则应在系统中的其他位置应用反压。
未必一定是“一旦未来完成,它就不会被引用到任何地方”。例如,参考它的客户可以在任何时候通过get()
方法请求结果。因此,JVM需要保留Future
直到所有这些外部引用都被删除。当Future
“完成”(即完成其任务或被取消)时,线程池中的引用将被删除。
感谢您指出这一点。但是,我使用的是executorService而不是ThreadPoolExecutor。而ExecutorService似乎没有'purge()'方法。 –
谢谢!并且ExecutorService被传递给我的代码,并通过在该ExecutorService上调用submit()来创建期货。该执行者服务即使完成,仍将继续参照期货。我不认为有办法告诉executorService清除已完成的期货:(。 –
)ExecutorService将一直完成时不会持有通过submit()提交的任务的引用。如果在运行程序中有其他地方提到'Future',可以关注这个问题 –
Thanks @ andrew-bissell! –