我正在将Callable对象提交到ThreadPoolExecutor,它们似乎在内存中停留。

使用Eclipse的MAT工具查看堆转储,您可以看到Callable对象由FutureTask$Sync可调用变量引用。该FutureTask$SyncFutureTask sync 变量引用。该FutureTaskFutureTask$Sync this $ 0 变量引用。

我已经阅读了有关此内容的信息(herehere,等等),似乎可调用对象包装在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被垃圾收集且不会永远泄漏?

最佳答案

根据this post,您可以在执行程序上调用purge

关于java - 如何确保将FutureTask的垃圾回收提交给ThreadPoolExecutor然后取消?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/4917039/

10-12 23:43