1

クラス内の Finalize メソッドはThreadPoolExecutor以下のようになります。

protected void finalize()  {
    shutdown();
}

スレッドが決して終了しない以下のプログラムを検討してください

ExecutorService executorService = Executors.newSingleThreadExecutor();
    executorService.submit(new Runnable() {
        @Override
        public void run() {
            try {
                new SynchronousQueue<String>()
                        .put("will never get removed");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    });
    executorService = null;
    System.gc();

}

そのような場合、少なくともJVMがその場合に終了するshutdownNowよりも良い選択でした。shutdown

アップデート:

finalizeメソッドを呼び出す理由の唯一の可能な説明shutdownは、プログラマーが明示的に呼び出さない場合、GC が防御メカニズムとして呼び出されることです。上記の場合、JVM は終了しないため、このメカニズムに欠陥があることがわかります。

4

3 に答える 3

4

まず、質問させてください: 決して終了しないスレッドをプールする必要があるのはなぜですか? オブジェクトをプールして再利用します。

Java が shutdown を呼び出す理由は、スレッドに正常に終了する機会を与えるためです。

スレッドを無限ループで実行する必要がある場合、スレッドはThread.currentThread().isInterrupted()false を返すことを確認してから、から戻る必要がありrun()ます。

あなたが示した例offer()では、タイムアウトではなくメソッドを使用したい場合がありput()ます。

最悪のシナリオでは、ファイナライザーを拡張ThreadPoolExecutorして呼び出すことができますshutdownNow()

于 2012-09-22T16:00:36.030 に答える
2

この話の教訓は、ThreadPool をシャットダウンしたい場合、ファイナライズに頼るべきではないということです。これは Java のすべてのリソースに当てはまります。ファイナライズ メカニズムに依存するべきではありません (決して実行されない可能性があるため)。ThreadPool をシャットダウンする場合は、自分で管理する必要があります。

finalize メソッドでのshutdown()呼び出しは、プログラマーが "偶然" ThreadPool を見失った場合の合理的な妥協案です。現在のタスクが完了するまで実行され、プールがシャットダウンされます。使用した場合shutdownNow()、ランダムな時点で (gc に応じて)、タスクが中断されます。おそらく理想的ではありません。また、呼び出されたかどうかに関係なく、シャットダウンを拒否するタスクをいつでも作成できます (例の try/catch ブロックの周りにループを追加するだけです)shutdown()shutdownNow()while(true)

于 2012-09-22T16:15:04.713 に答える
0

shutdown()呼び出されると、プールは新しいタスクを受け入れず、送信されたタスクが完了した後に実際に「シャットダウン」することを意味します。あなたの場合、必要shutdownNow()な場所で明示的に呼び出す方がよいでしょう。

于 2012-09-22T16:05:42.173 に答える