このスレッドプールはなぜガベージコレクションされないのでしょうか? 質問する

このスレッドプールはなぜガベージコレクションされないのでしょうか? 質問する

このコード例では、ExecutorService が 1 つ使用され、スコープ外になることが許可されています。

public static void main(String[] args)
{
    ExecutorService executorService = Executors.newFixedThreadPool(3);
    executorService.submit(new Runnable()
    {
        public void run()
        {
            System.out.println("hello");
        }
    });
}

executorService がスコープ外になると、収集されて終了処理される必要があります。ThreadPoolExecutor の finalize() メソッドは、shutdown() を呼び出します。

/**
 * Invokes {@code shutdown} when this executor is no longer
 * referenced and it has no threads.
 */
protected void finalize() {
    shutdown();
}

いったんshutdown()が呼び出されると、プールスレッドは終了し、JVMは終了できるはずです。しかし、executorServiceは収集されないため、JVMは存続します。System.gc()の呼び出しも機能していないようです。main()が終了した後でもexecutorServiceが収集されないのはなぜでしょうか?

注: 自分でshutdown()を呼び出す必要があることはわかっており、テスト以外では常に実行しています。ここでファイナライズがバックアップとして機能しないのはなぜか不思議です。

ベストアンサー1

これは、GC が非決定的であることとはまったく関係ありませんが、役に立ちません。(これはあなたの例の原因の 1 つですが、メモリを消費してコレクションを強制するように「修正」したとしても、それでもファイナライズされません)

エグゼキュータが作成するワーカー スレッドは、エグゼキュータ自体への参照を持つ内部クラスです。(キュー、実行状態などを確認するために必要です。) 実行中のスレッドはガベージ コレクションされないため、プール内の各スレッドがその参照を持つと、すべてのスレッドが終了するまでエグゼキュータは存続します。手動でスレッドを停止しないと、スレッドは永久に実行され続け、JVM はシャットダウンされません。

おすすめ記事