我正在将Callable
对象提交到ThreadPoolExecutor
,它们似乎在内存中停留。
使用Eclipse的MAT工具查看堆转储,您可以看到Callable
对象由FutureTask$Sync
的可调用变量引用。该FutureTask$Sync
由FutureTask
的 sync 变量引用。该FutureTask
由FutureTask$Sync
的 this $ 0 变量引用。
我已经阅读了有关此内容的信息(here,here,等等),似乎可调用对象包装在FutureTask
的Submit()上的ThreadPoolExecutor
拥有对可调用对象的永久引用。
我感到困惑的是如何确保FutureTask
被垃圾回收,以使其不再继续将可调用对象保存在内存中,而不保存可调用对象可能保存在内存中的任何内容?
只是为了提供有关我的特定情况的更多详细信息,我正在尝试以某种方式实现ThreadPoolExecutor
,该方式允许在需要时取消所有已提交的任务。我尝试了在SO和其他地方发现的几种不同方法,例如完全关闭执行程序(使用shutdown()
,shutdownNow()
等),还保留submit()
的 future yield 列表,并在所有方法上调用cancel,然后清除 future 。理想情况下,我不想关闭它,只需要添加cancel()
并在需要时清除它即可。
所有这些方法似乎都没有作用。如果我将可调用对象提交到池中,则很有可能最终会卡住。
我究竟做错了什么?
谢谢。
编辑:
根据要求,这是ThreadPoolExecutor的构造函数。
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) {
super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
}
经过进一步的测试后,我可以看到,如果让已提交给ThreadPoolExecutor的任务完成,则不会泄漏。如果我尝试以任何方式取消它们,例如:
shutdownNow()
或保存对将来的引用并在以后调用cancel:
Future referenceToCancelLater = submit(task);
...
referenceToCancelLater.cancel(false);
或者使用以下方法将它们从队列中删除:
getQueue.drainTo(someList)
或者
getQueue.clear()
或者
遍历保存的 future 引用并调用:
getQueue.remove(task)
这些情况中的任何一种都会导致FutureTask停留在上面,如上所述。
因此,所有这一切的真正问题是,如何正确地从ThreadPoolExecutor中取消或删除项目,以便FutureTask被垃圾收集且不会永远泄漏?
最佳答案
关于java - 如何确保将FutureTask的垃圾回收提交给ThreadPoolExecutor然后取消?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/4917039/