为什么从 Executors 实用程序 class 返回的 ExecutorService 的 execute() 方法无法自然终止
Why does the execute() method of ExecutorService returned from Executors utility class could not terminate naturally
据我们所知,java.util.concurrent.Executors
包含许多方法,例如
newCachedThreadPool
newFixedThreadPool
newScheduledThreadPool
newSingleThreadExecutor
newSingleThreadScheduledExecutor
它们returnExecutorService
,其中包含execute(Runnable task)
方法。但是,当从上述工厂方法调用ExecutorService
return的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
编辑的 return 可以在不调用 shutdown()
或 shutdownNow()
所以我的问题是:为什么 ExecutorService
return 的 execute()
来自上述 工厂方法 从设计的角度来看,如果不调用 shutdown()
或 shutdownNow()
,以“new”开始不会终止?
Rui,您的示例挂起的原因很简单。默认情况下,ExecutorService 中的线程是非守护线程,只要有非守护线程运行,Java 程序就不会退出。如果您不想要这种行为,您需要做的就是定义一个创建守护线程的 ThreadFactory,如下所示:
public class Test {
static ThreadFactory mThreadFactory = new ThreadFactory() {
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
t.setDaemon(true);
return t;
}
};
public static void main(String[] args) {
ExecutorService e = Executors.newSingleThreadExecutor(mThreadFactory);
e.execute(new Runnable() { public void run() { System.out.println("test"); } });
}
}
简要介绍java线程:有两种类型的线程——守护进程和非守护进程。当所有非守护线程都完成执行时,程序终止。守护线程只能 运行 只要程序是 运行ning 并且不阻止终止,例如garbage collector。当 java 程序启动时,除主线程外的所有线程都是守护进程。
newSingleThreadExecutor()
及其 defaultThreadFactory()
创建非守护线程。这有点道理 - 您正在创建一个等待工作的 线程 池,您应该明确打算将其关闭。
另一方面,ForkJoinPool 将您从底层线程池中抽象出来。所以它可以使用守护线程,因为通常你打算等待任务执行。
据我们所知,java.util.concurrent.Executors
包含许多方法,例如
newCachedThreadPool
newFixedThreadPool
newScheduledThreadPool
newSingleThreadExecutor
newSingleThreadScheduledExecutor
它们return
ExecutorService
,其中包含execute(Runnable task)
方法。但是,当从上述工厂方法调用ExecutorService
return的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
编辑的 return 可以在不调用 shutdown()
或 shutdownNow()
所以我的问题是:为什么 ExecutorService
return 的 execute()
来自上述 工厂方法 从设计的角度来看,如果不调用 shutdown()
或 shutdownNow()
,以“new”开始不会终止?
Rui,您的示例挂起的原因很简单。默认情况下,ExecutorService 中的线程是非守护线程,只要有非守护线程运行,Java 程序就不会退出。如果您不想要这种行为,您需要做的就是定义一个创建守护线程的 ThreadFactory,如下所示:
public class Test {
static ThreadFactory mThreadFactory = new ThreadFactory() {
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
t.setDaemon(true);
return t;
}
};
public static void main(String[] args) {
ExecutorService e = Executors.newSingleThreadExecutor(mThreadFactory);
e.execute(new Runnable() { public void run() { System.out.println("test"); } });
}
}
简要介绍java线程:有两种类型的线程——守护进程和非守护进程。当所有非守护线程都完成执行时,程序终止。守护线程只能 运行 只要程序是 运行ning 并且不阻止终止,例如garbage collector。当 java 程序启动时,除主线程外的所有线程都是守护进程。
newSingleThreadExecutor()
及其 defaultThreadFactory()
创建非守护线程。这有点道理 - 您正在创建一个等待工作的 线程 池,您应该明确打算将其关闭。
另一方面,ForkJoinPool 将您从底层线程池中抽象出来。所以它可以使用守护线程,因为通常你打算等待任务执行。