Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/368.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何确保提交给ThreadPoolExecutor然后取消的FutureTask的垃圾收集?_Java_Memory Leaks_Executor_Callable_Futuretask - Fatal编程技术网

Java 如何确保提交给ThreadPoolExecutor然后取消的FutureTask的垃圾收集?

Java 如何确保提交给ThreadPoolExecutor然后取消的FutureTask的垃圾收集?,java,memory-leaks,executor,callable,futuretask,Java,Memory Leaks,Executor,Callable,Futuretask,我正在将Callable对象提交给ThreadPoolExecutor,它们似乎在内存中停留 使用Eclipse的MAT工具查看堆转储,可以看到Callable对象被FutureTask$Sync的Callable变量引用。FutureTask$Sync由FutureTask的Sync变量引用。该FutureTask由FutureTask$Sync的此$0变量引用 我已经阅读了这方面的内容(,等等),似乎FutureTask中包含了可调用的内容,而ThreadPoolExecutor的submi

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

使用Eclipse的MAT工具查看堆转储,可以看到
Callable
对象被
FutureTask$Sync
Callable变量引用。
FutureTask$Sync
FutureTask
Sync变量引用。该
FutureTask
FutureTask$Sync
此$0变量引用

我已经阅读了这方面的内容(,等等),似乎
FutureTask
中包含了可调用的内容,而
ThreadPoolExecutor
的submit()永远保存着对可调用内容的引用

我所困惑的是如何确保
FutureTask
被垃圾收集,这样它就不会继续在内存中保存可调用的内容,也不会保存可调用的内容在内存中

为了更详细地说明我的具体情况,我正在尝试以一种允许在需要时取消所有提交的任务的方式实现
ThreadPoolExecutor
。我在SO和其他地方尝试了几种不同的方法,例如完全关闭执行器(使用
shutdown()
shutdownNow()
等),还通过
submit()
保存期货回报列表,并对所有这些方法调用cancel,然后清除期货列表。理想情况下,我希望不必关闭它,只需
cancel()
并在需要时清除

所有这些方法似乎都没有什么不同。如果我向游泳池提交了一份催缴单,那么它很有可能最终会留下来

我做错了什么

谢谢

编辑:

根据要求,这里是ThreadPoolExecutor的构造函数

public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) {
    super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
}
或者保存对未来的引用并稍后调用cancel:

Future referenceToCancelLater = submit(task);
...
referenceToCancelLater.cancel(false);
或者使用以下方法将其从队列中删除:

getQueue.drainTo(someList)

或 通过保存的对未来的引用循环并调用:

getQueue.remove(task)
上述任何一种情况都会导致FutureTask停留在上述位置


因此,所有这一切的真正问题是如何正确地取消或删除ThreadPoolExecutor中的项目,以便FutureTask被垃圾收集,而不会永远泄漏?

作为一种解决方法,您可以执行以下操作:

class ClearingCallable<T> implements Callable<T> {
    Callable<T> delegate;
    ClearingCallable(Callable<T> delegate) {
        this.delegate = delegate;
    }

    T call() {
        try {
            return delegate.call();
        } finally {
            delegate = null;
        }
    }
}
class ClearingCallable实现了可调用{
可调用代表;
ClearingCallable(可调用委托){
this.delegate=委托;
}
T call(){
试一试{
返回delegate.call();
}最后{
delegate=null;
}
}
}

我什么都做不到,所以我想出了以下解决方案。这里是一个粗略的概述:我在ThreadPoolExecutor中创建了一个数组,用于跟踪队列中的可运行程序。然后,当我需要取消队列时,我循环遍历并在每个可运行程序上调用cancel方法。在我的例子中,所有这些可运行文件都是我创建的自定义类,它们的cancel方法只是设置了一个cancelled标志。当队列调出下一个要处理的队列时,在runnable的运行中,它会看到它被取消,并跳过实际的工作

所以所有的runnables都会很快一个接一个地被冲掉,因为它看到它被取消了

可能不是最好的解决方案,但它对我有效,而且不会泄漏内存

根据,您可以拜访执行人。

参考:

未来表示异步计算的结果。如果无法使用get方法检索结果,则会发生内存泄漏


如果您不想使用异步结果,请使用Runnable install Callable。

在这种情况下,委托是什么?您的Callable保持希望垃圾收集的状态。这解决不了任何问题。问题不在于
ThreadPoolExecutor
,b/c它本身不会泄漏已执行的任务,而在于未来的任务,它保存了我希望被垃圾收集的可调用对象。查看堆,我不明白为什么不收集它。所以问题是返回的对象被保留了?因此,另一种覆盖裂缝的方法是,返回时说一个WeakReference,然后打电话澄清。当然,您仍然在泄漏小对象。发布您的代码,作为硬删除方式:
ThreadPoolExecutor.getQueue()。删除(未来)
将完成此任务。这里讨论了是否应该以这种方式使用getQueue()。这样做真的有缺点吗?@bestsss我希望不会有人问我;)代码中有很多内容,我不确定哪些部分与此问题相关。我希望对未来任务中可能导致泄漏的原因有一个大致的了解。是否有一个特定的部分您想看到?@ LITTLE FLUFFY KITY,因为您可以创建队列本身(并且我确实有奇怪的队列W/Stand线程调度策略),您可以将其视为代码> TracePoLeExcel Outue/Copy> API的一部分,使用它自己的意愿(Piell)。code>ThreadPoolExecutor使用类似于Shutdownow()上的队列。同样,您的问题不是队列。您正在其他地方泄漏smth此问题作为JDK bug 6602600()提交。您好,我想我遇到了与您相同的问题。你有没有想到如何用吸尘器解决这个问题;)路?实际上,应该有一些Java类负责删除那些过期的线程。Cheers@Simone不幸的是,没有,我找不到更内置的东西。我仍在使用上述方法。它的工作只是很好,只是需要一些努力来获得设置。感谢您的回复。那么,cancel方法(Runnable类)是释放线程分配的内存还是手动释放
getQueue.remove(task)
class ClearingCallable<T> implements Callable<T> {
    Callable<T> delegate;
    ClearingCallable(Callable<T> delegate) {
        this.delegate = delegate;
    }

    T call() {
        try {
            return delegate.call();
        } finally {
            delegate = null;
        }
    }
}