78

との基本的な違いを知りたいshutdown()shutdownNow()ですがExecutor Service

私が理解した限り:

shutdown()グレースフルシャットダウンに使用する必要があります。つまり、実行中であり、処理のためにキューに入れられたが、開始されていないすべてのタスクの完了を許可する必要があります。

shutdownNow()突然のシャットダウンを実行します。これは、一部の未完了のタスクがキャンセルされ、未開始のタスクもキャンセルされることを意味します。私が見逃している暗黙的/明示的なものは他にありますか?

PS:これに関連するエグゼキュータサービスをシャットダウンする方法について別の質問を見つけましたが、正確には知りたいことではありません。

4

3 に答える 3

145

要約すると、あなたはそれをそのように考えることができます:

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

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

  • を使用すると、実行中のタスクが中断されshutdownに実行を継続するため、出力が行われます。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...");
}
于 2012-07-17T10:05:14.240 に答える
8
  • shutdown()

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

  • shutdownNow()

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

于 2015-09-15T10:00:33.873 に答える
2

javadocsから:

void shutdown

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

List<Runnable> shutdownNow()

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

アクティブに実行されているタスクの処理を停止するための最善の試み以外の保証はありません。

たとえば、通常の実装はThread.interrupt()を介してキャンセルされるため、割り込みに応答できないタスクは決して終了しない可能性があります。

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

于 2012-07-17T10:06:04.237 に答える