web-dev-qa-db-ja.com

ExecutorServiceをシャットダウンする方法は?

shutdownNow()またはshutdown()を呼び出すたびにシャットダウンしません。私は、シャットダウンが保証されていないことを言っているいくつかのスレッドを読みました。

39
rosesr

典型的なパターンは次のとおりです。

_executorService.shutdownNow();
executorService.awaitTermination();
_

shutdownNowを呼び出すと、executorは(一般に)管理するスレッドを中断しようとします。シャットダウンを正常に行うには、スレッドで割り込み例外をキャッチするか、割り込みステータスを確認する必要があります。そうしないと、スレッドは永久に実行され、エグゼキューターはシャットダウンできなくなります。これは、Javaでのスレッドの中断は協調プロセスであるためです(つまり、interruptedコードは、interrupting)ではなく、停止を要求されたときに何かを行う必要がありますコード)。

たとえば、次のコードは_Exiting normally..._を出力します。ただし、行if (Thread.currentThread().isInterrupted()) break;をコメント化すると、executor内のスレッドがまだ実行されているため、_Still waiting..._が出力されます。

_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()) break;
            }
        }
    });

    executor.shutdownNow();
    if (!executor.awaitTermination(100, TimeUnit.MICROSECONDS)) {
        System.out.println("Still waiting...");
        System.exit(0);
    }
    System.out.println("Exiting normally...");
}
_

あるいは、次のようにInterruptedExceptionで書くこともできます。

_public static void main(String args[]) throws InterruptedException {
    ExecutorService executor = Executors.newFixedThreadPool(1);
    executor.submit(new Runnable() {

        @Override
        public void run() {
            try {
                while (true) {Thread.sleep(10);}
            } catch (InterruptedException e) {
                //ok let's get out of here
            }
        }
    });

    executor.shutdownNow();
    if (!executor.awaitTermination(100, TimeUnit.MICROSECONDS)) {
        System.out.println("Still waiting...");
        System.exit(0);
    }
    System.out.println("Exiting normally...");
}
_
83
assylias

最良の方法は、javadocに実際にあるものです:

次のメソッドは、2つの段階でExecutorServiceをシャットダウンします。最初にshutdownを呼び出して着信タスクを拒否し、次に必要に応じてshutdownNowを呼び出して残留タスクをキャンセルします:

void shutdownAndAwaitTermination(ExecutorService pool) {
    pool.shutdown(); // Disable new tasks from being submitted
    try {
        // Wait a while for existing tasks to terminate
        if (!pool.awaitTermination(60, TimeUnit.SECONDS)) {
            pool.shutdownNow(); // Cancel currently executing tasks
            // Wait a while for tasks to respond to being cancelled
            if (!pool.awaitTermination(60, TimeUnit.SECONDS))
                System.err.println("Pool did not terminate");
        }
    } catch (InterruptedException ie) {
        // (Re-)Cancel if current thread also interrupted
        pool.shutdownNow();
        // Preserve interrupt status
        Thread.currentThread().interrupt();
    }
}
19
Nicolas Filotto