简体   繁体   English

如何关闭 ExecutorService?

[英]How to shutdown an ExecutorService?

Whenever I call shutdownNow() or shutdown() it doesn't shut down.每当我调用shutdownNow()shutdown()时,它都不会关闭。 I read of a few threads where it said that shutting down is not guaranteed - can someone provide me a good way of doing it?我读过一些帖子说不能保证关闭 - 有人可以为我提供一个好的方法吗?

The typical pattern is:典型的模式是:

executorService.shutdownNow();
executorService.awaitTermination();

When calling shutdownNow , the executor will (generally) try to interrupt the threads that it manages.当调用shutdownNow时,执行程序(通常)会尝试中断它管理的线程。 To make the shutdown graceful, you need to catch the interrupted exception in the threads or check the interrupted status.要使关闭优雅,您需要在线程中捕获中断的异常或检查中断状态。 If you don't your threads will run forever and your executor will never be able to shutdown.如果您不这样做,您的线程将永远运行,您的执行程序将永远无法关闭。 This is because the interruption of threads in Java is a collaborative process (ie the interrupted code must do something when asked to stop, not the interrupting code).这是因为Java 中线程的中断是一个协作过程(即被中断的代码在被要求停止时必须做某事,而不是中断的代码)。

For example, the following code prints Exiting normally... .例如,以下代码打印Exiting normally... But if you comment out the line if (Thread.currentThread().isInterrupted()) break;但是如果你注释掉这一行if (Thread.currentThread().isInterrupted()) break; , it will print Still waiting... because the threads within the executor are still running. ,它将打印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...");
}

Alternatively, it could be written with an InterruptedException like this:或者,它可以用这样的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...");
}

The best way is what we actually have in the javadoc which is:最好的方法是我们在 javadoc 中实际拥有的内容:

The following method shuts down an ExecutorService in two phases, first by calling shutdown to reject incoming tasks, and then calling shutdownNow , if necessary, to cancel any lingering tasks:以下方法分两个阶段关闭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();
    }
}

Java 19 makes ExecutorService implement AutoCloseable , meaning it shuts down when exiting a try-with-resources block: Java 19 使ExecutorService implement AutoCloseable ,这意味着它在退出 try-with-resources 块时关闭:

try (ExecutorService e = Executors.newFixedThreadPool(2)) {
   e.submit(task1);
   e.submit(task2);
} // blocks and waits

This is a structured concurrency approach developed as part of Project Loom , which is incubating in Java 19. As of July 2022, Java 19 is not officially released but early access builds are available.这是作为Project Loom的一部分开发的结构化并发方法,该方法正在 Java 19 中进行孵化。截至 2022 年 7 月,Java 19 尚未正式发布,但可以使用早期访问版本。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM