执行与执行服务之间的区别


67

我想知道shutdown()shutdownNow()关闭之间的基本区别Executor Service

据我了解:

shutdown()应该用于正常关机,这意味着应该允许所有正在运行并排队等待处理但尚未启动的任务完成

shutdownNow()做一个突然的关机意味着一些未完成的任务被取消,尚未启动的任务也被取消。还有其他我不知道的隐式/显式信息吗?

PS:我发现了另一个问题,该问题是如何关闭与此相关的执行程序服务,但并不是我想知道的。


6
您是否阅读了这两种方法的API文档?它准确地解释了每种方法的作用。
杰斯珀,

那也是我的方法。我通常调用shutdown(),如果任务没有在特定时间内完成,我调用shutdownNow()强制关闭。到目前为止效果很好。
哈科·范·尼克尔

2
仅来自api文档的@Jesper我收集了这些信息。我想知道是否还有其他我想念的东西。
极客

2
@downvoter为什么要投反对票?它缺乏研究努力还是什么?关于拒绝投票的理由有何建设性意见?
极客

1
是的,这表明缺乏研究。您基本上会问一些在javadoc中可以回答的问题。
JB Nizet

Answers:


129

总之,您可以这样考虑:

  • 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...");
}

1
请回答我:shutDownNow()是否会中断所有仍在运行任务的线程?和shutDown()和shutDownNow()之间的共同点是取消尚未分配给任何线程的待处理任务?
Android开发人员

4
是/否:关机不会取消等待的任务,只会阻止提交新任务。但是只要线程可用,已经提交的任务就会运行。
assylias 2014年

8
更令人困惑的是,在doc API中,它说shutdown()This method does not wait for previously submitted tasks to complete execution. Use awaitTermination to do that.表示不等待,这与该答案相反。
supertonsky

6
@supertonsky“它不会等待”,在这种情况下,意味着调用shutdown立即返回,而不会阻塞(awaitTermination不会阻塞)。但是,它可以使先前提交的任务完成其工作。
assylias's

5
@MarounMaroun当线程被中断时,其中断标志设置为true。就是这样,中断不会停止线程(也不会引发中断)。因此,您需要定期检查该中断标志,并在捕获该中断标志时正常退出(通常是通过退出(如示例中那样),或者抛出InterruptedException)。在示例中,当条件消除后,您需要使用System.exit(0)强制终止程序,否则它将无限期地运行。
assylias 2016年

7
  • shutdown()

要终止ExecutorService内部的线程,请调用其shutdown()方法。ExecutorService不会立即关闭,但将不再接受新任务,并且一旦所有线程都完成了当前任务,ExecutorService就会关闭。调用shutdown()之前提交给ExecutorService的所有任务都将执行。

  • shutdownNow()

如果要立即关闭ExecutorService,可以调用该shutdownNow()方法。这将尝试立即停止所有正在执行的任务,并跳过所有已提交但未处理的任务。不能保证执行任务。也许他们停下来,也许执行到最后。这是尽力而为的尝试。


2

javadocs

void shutdown

启动有序关闭,在该关闭中执行先前提交的任务,但不接受任何新任务。

List<Runnable> shutdownNow()

尝试停止所有正在执行的任务,暂停正在等待的任务的处理,并返回正在等待执行的任务的列表。

尽最大努力,尝试不保证可以停止处理正在执行的任务。

例如,典型的实现将通过Thread.interrupt()取消,因此任何无法响应中断的任务都可能永远不会终止。

返回:从未开始执行的任务列表

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.