web-dev-qa-db-ja.com

Executor ServiceのshutdownとshutdownNowの違い

Executor Serviceをシャットダウンするためのshutdown()shutdownNow()の基本的な違いを知りたいですか?理解した限りでは、shutdown()に使用する必要がありますgracefulshutdownは、実行中で処理のためにキューに入れられていて開始されていないすべてのタスクの完了を許可し、shutdownNow()abruptshutdownの意味を行いますいくつかの未完了のタスクはキャンセルされ、未開始のタスクもキャンセルされます。私が見逃している暗黙的/明示的なものは他にありますか?

追伸: [〜#〜] so [〜#〜] に関連する別の質問を見つけましたが、正確に知りたいことではありません。

62
Geek

要約すると、次のように考えることができます。

  • shutdown()は、executorサービスに新しいタスクを受け入れられないことを通知しますが、既に送信されたタスクは引き続き実行されます
  • shutdownNow()は同じことを行い、キャンセルを試みる関連するスレッドを中断することにより、すでに送信されたタスクを行います。タスクが中断を無視する場合、shutdownNowshutdownとまったく同じように動作することに注意してください。

以下の例を試して、shutdownshutdownNowに置き換えると、実行のさまざまなパスをよりよく理解できます。

  • shutdownの場合、実行中のタスクはnotで中断され、実行を継続するため、出力はStill waiting after 100ms: calling System.exit(0)...です。
  • shutdownNowの場合、出力はinterruptedおよび_Exiting normally..._になります。これは、実行中のタスクが中断され、中断をキャッチしてから実行を停止する(whileループを中断する)ためです。
  • shutdownNowを使用すると、whileループ内の行をコメントアウトすると、実行中のタスクによって中断が処理されなくなるため、Still waiting after 100ms: calling System.exit(0)...が返されます。
_public static void main(String[] args) throws InterruptedException {
    ExecutorService executor = Executors.newFixedThreadPool(1);
    executor.submit(new Runnable() {

        @Override
        public void run() {
            while (true) {
                if (Thread.currentThread().isInterrupted()) {
                    System.out.println("interrupted");
                    break;
                }
            }
        }
    });

    executor.shutdown();
    if (!executor.awaitTermination(100, TimeUnit.MICROSECONDS)) {
        System.out.println("Still waiting after 100ms: calling System.exit(0)...");
        System.exit(0);
    }
    System.out.println("Exiting normally...");
}
_
116
assylias
  • shutdown()

ExecutorService内のスレッドを終了するには、そのshutdown()メソッドを呼び出します。 ExecutorServiceはすぐにシャットダウンしませんが、新しいタスクを受け入れなくなり、すべてのスレッドが現在のタスクを完了すると、ExecutorServiceはシャットダウンします。 shutdown()が呼び出される前にExecutorServiceに送信されたすべてのタスクが実行されます。

  • shutdownNow()

ExecutorServiceをすぐにシャットダウンする場合は、shutdownNow()メソッドを呼び出すことができます。これにより、実行中のすべてのタスクがすぐに停止され、送信されたが処理されていないすべてのタスクがスキップされます。実行中のタスクについての保証はありません。おそらくそれらは停止し、おそらく最後まで実行されます。これはベストエフォートの試みです。

5
Ahmed MANSOUR

javadocs から:

_void shutdown_

以前に送信されたタスクが実行されますが、新しいタスクは受け入れられない、正常なシャットダウンを開始します。

List<Runnable> shutdownNow()

アクティブに実行中のすべてのタスクを停止し、待機中のタスクの処理を停止し、実行を待機していたタスクのリストを返します。

タスクの実行をアクティブに処理を停止するためのベストエフォートの試み以外の保証はありません実行タスク。

たとえば、典型的な実装はThread.interrupt()によってキャンセルされるため、割り込みへの応答に失敗したタスクは終了することはありません。

戻り値:実行を開始したことがないタスクのリスト

2
fmucar