【问题标题】:How to shutdown an ExecutorService?如何关闭 ExecutorService?
【发布时间】:2012-05-17 06:21:25
【问题描述】:

每当我拨打shutdownNow()shutdown() 时,它都不会关闭。我读过一些帖子,上面说不能保证关闭 - 有人可以为我提供一个好的方法吗?

【问题讨论】:

  • 请将正确答案标记为已接受

标签: java multithreading executorservice shutdown


【解决方案1】:

最好的方法是我们在 javadoc 中实际拥有的:

以下方法分两个阶段关闭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();
    }
}

【讨论】:

    【解决方案2】:

    典型的模式是:

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

    当调用shutdownNow 时,执行程序(通常)会尝试中断它管理的线程。要使关闭优雅,您需要在线程中捕获中断的异常或检查中断状态。如果您不这样做,您的线程将永远运行,您的执行程序将永远无法关闭。这是因为 Java 中线程的中断是一个协作过程(即,当要求停止时,中断代码必须做某事,而不是中断代码)。

    例如,以下代码打印Exiting normally...。但是如果你注释掉if (Thread.currentThread().isInterrupted()) break;这一行,它将打印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...");
    }
    

    【讨论】:

    • 你知道shutdown是否也启动Thread.interrupt(),从Java API看来shutdown似乎没有中断线程?
    • @Bionix1441 不,它没有。 shutdownNow 确实如此。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多