2009-07-31 6 views
9

Brian GoetzのJava Concurrency in Practice JVMはすべての(nondaemon)スレッドが終了するまで終了できないため、ExecutorをシャットダウンできないとJVMが終了しない可能性があります。アプリケーションを終了するときにすべてのエグゼキュータをシャットダウンする方法はありますか?

e.e.e. Executorが周囲にある場合、System.exit(0)は必ずしも期待どおりに機能しません。 Executorを含むすべてのクラスに対して、何らかの種類を入れてからアプリケーションが終了しようとしているときに呼び出す必要があるようです。これは唯一の方法ですか、またはExecutorsをすべてシャットダウンするためのショートカットがありますか?

+0

私はExecutorとRunnableを混同していました。あまり意味がないので私の答えを削除しました。 @スカフマンは私の投票権を持っています。 –

答えて

14

これらをすべて実行するショートカットはありません。また、shutdown()ではなくshutdownNow()に電話する必要があります。そうしないと、しばらく待つことになります。

あなたが実行できることは、Executorを作成して中央の場所に登録することです。その後、シャットダウンするときには、そのセントラルオブジェクトにshutdown()を呼び出すだけで、登録済みエグゼキュータのそれぞれを終了させることができます。

Springを使用する場合は、Executorを作成および管理するファクトリBeanを利用できます。これには、アプリケーションが終了したときに正常にシャットダウンし、自分で管理する必要がなくなります。

+0

セントラルレジスタは合理的な選択肢のようです。面白いことにjava.util.concurrentにはそのようなものは含まれていません。 –

+0

また、Executorsは数多くの静的なメソッドなので、数十個のメソッドシグネチャを複製せずに登録インターフェイスの背後に隠すことは難しいです。 – skaffman

+0

私も同様の問題に直面しています。私は明示的にScheduledThreadPoolExecutorを使用していません。だから、私は同じことについての中心的な参照を持っていない。そのような場合、どのようにこれらのスレッドプールにアクセスするのですか?私は正常にContextDestroyedメソッドでそれらをシャットダウンしようとしています – DecKno

0

おそらく、彼は、Nondaemonスレッドが終了するまで、JVMはそれ自身で停止することはできないと言っていたでしょう。そのようなjavaのSomeClassのようなコマンドから単純なクラスを実行し、メインメソッドの実行後にJVMが停止します。

System.exitはJVM終了コマンドです。デーモンスレッドが実行されている場合でも、JVMはシャットダウンします。

+1

Goetzが書いたように、* nondaemon *スレッドは、JVMが終了するのを防ぐことができます。実際に私はこれを経験しました。デバッガは、アプリがシステムに詰まることを示しています。無限に終了する(0)が、非決定論的な振る舞いに見える。通常、ジャムはしませんが、ときどき起こります。 –

5

作成したスレッドをデーモンスレッドとしてマークするThreadFactoryの実装を提供することもできます。私はクリーンなシャットダウンメカニズム(ライフサイクルメソッドあり)が好きですが、これが適切な場合に未完了タスクの状態/完了について保証する必要がない場合があります。

+0

このオプションを指摘してくれてありがとう。実際にエグゼキュータの一部はデーモンスレッドでなければなりません。Executors.newXXXExecutor():sがデフォルトで実行するのは、デーモンではないデーモンです。 –

7

デフォルトでは、エグゼキュータは非デーモンスレッドのみを作成します。 Executorに独自のThreadFactoryを指定することで、それをオーバーライドすることができます。ここでは例です:JVMは、これらのスレッドが有益な仕事をして忙しくしていてもすぐにをを終了しますので、

class DaemonThreadFactory implements ThreadFactory { 
    public Thread newThread(Runnable r) { 
    Thread t = new Thread(r); 
    t.setDaemon(true); 
    return t; 
    } 
} 

は、しかし、注意してください!

8

com.google.common.util.concurrent.MoreExecutors#getExitingExecutorService

@Beta 
public static ExecutorService getExitingExecutorService(ThreadPoolExecutor executor, 
             long terminationTimeout, 
             TimeUnit timeUnit) 

とエグゼキュータを飾るは、アプリケーションが完了すると終了ExecutorServiceのに所与ThreadPoolExecutorを変換します。これは、デーモンスレッドを使用し、シャットダウンフックを追加して完了を待つことで実行されます。

これは主に固定スレッドプール用です。 Executors.newFixedThreadPool(int)を参照してください。

関連する問題