众所周知,java.util.concurrent.Executors
包含许多方法,例如
newCachedThreadPool
newFixedThreadPool
newScheduledThreadPool
newSingleThreadExecutor
newSingleThreadScheduledExecutor
它们返回
来终止。ExecutorService
,其中包含execute(Runnable task)
方法。然而,当调用上述工厂方法返回的ExecutorService
的execute(Runnable task)
时,只能通过调用shutdown()
或shutdownNow()
例如,如果我们将以下代码添加到 main
方法中,
ExecutorService e = Executors.newSingleThreadExecutor();
e.execute(() -> system.out.println("test"));
调用主程序永远不会终止,因为 shutdown()
或 shutdownNow()
未被调用。因此,在 main 中包含以下代码片段的程序将终止
ExecutorService e = Executors.newSingleThreadExecutor();
e.execute(() -> system.out.println("test"));
e.shutdown();
但是,ExecutorService
的某些子类(例如通过调用 Executors.newWorkStealingPool
或 ForkJoinPool
返回的子类)可以在不调用 shutdown()
或 shutdownNow()
的情况下终止
所以我的问题是:为什么从设计的角度来看,从上述以“new”开头的工厂方法返回的ExecutorService
的execute()
在不调用shutdown()
或shutdownNow()
的情况下不会终止?
最佳答案
简单介绍一下java线程:线程有两种类型——守护线程和非守护线程。当程序的所有非守护线程都完成执行时,程序将终止。守护线程只能在程序运行时运行,并且不会阻止终止,例如garbage collector 。当java程序启动时,除了主线程之外的所有线程都是守护进程。
newSingleThreadExecutor()
及其 defaultThreadFactory()
创建非守护线程。这是有道理的 - 您正在创建一个等待工作的线程池,您应该明确打算关闭它。
ForkJoinPool 另一方面,将您从底层线程池中抽象出来。因此它可以使用守护线程,因为通常您的意图是等待任务执行。
关于java - 为什么从Executors实用程序类返回的ExecutorService的execute()方法无法自然终止,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50754759/