ThreadPoolexecutorに提出されてからキャンセルされたFutureTaskのごみ収集を確保する方法は?
-
29-10-2019 - |
質問
提出しています Callable
aにオブジェクト ThreadPoolExecutor
そして、彼らは記憶に固執しているようです。
日食用のマットツールでヒープダンプを見る Callable
オブジェクトはaによって参照されています FutureTask$Sync
's 呼び出すことができます 変数。それか FutureTask$Sync
aによって参照されます FutureTask
's 同期 変数。それか FutureTask
を参照してください FutureTask$Sync
's この$ 0 変数。
私はこれについて読んでいます(ここ, ここ, 、そしてそう)そしてそれは FutureTask
呼び出し可能なものがに包まれていること ThreadPoolExecutor
's submit()は、通話可能なものへの参照を永遠に保持しています。
私が混乱しているのは、 FutureTask
ゴミを収集して、コールをメモリに保持し続けないようにし、呼び出し可能なものがメモリに保持されている可能性があるものを保持し続けますか?
私の特定の状況について詳しく説明するために、私は実装しようとしています ThreadPoolExecutor
必要に応じて、提出されたすべてのタスクをキャンセルできるようにする方法。私は、執行者を完全にシャットダウンするなど、私が見つけたいくつかの異なる方法を試しました( shutdown()
, shutdownNow()
等)そしてまた、先物のリターンのリストを維持する submit()
呼び出して、それらすべてをキャンセルし、先物リストをクリアします。理想的には、それをシャットダウンする必要はありません。 cancel()
必要に応じてクリアします。
これらの方法はすべて違いを生むようには見えません。プールに電話をかけることができる場合、それが固執する可能性が十分にあります。
私は何が間違っているのですか?
ありがとう。
編集:
要求されているように、こちらがthreadpoolexecutorのコンストラクターです。
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) {
super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
}
さらにテストした後、スレッドプールエクセクターに提出されたタスクを終了した場合、リークがないことがわかります。とにかくそれらをキャンセルしようとした場合:
shutdownNow()
または、将来への参照を保存し、後でキャンセルします:
Future referenceToCancelLater = submit(task);
...
referenceToCancelLater.cancel(false);
または、次のような方法でキューからそれらを削除することによって
getQueue.drainTo(someList)
また
getQueue.clear()
または、未来への保存された参照と呼び出しをループする:
getQueue.remove(task)
これらのケースは、上記のようにFutureTaskが固執します。
そのため、このすべての本当の質問は、FutureTaskがゴミを収集し、永遠に漏れないように、ThreadPoolexecutorからアイテムを適切にキャンセルまたは削除する方法です。
正しい解決策はありません