程序不会立即终止,当所有执行器服务任务都完成

我把一堆可运行的对象放到一个执行器服务中:

// simplified content of main method
ExecutorService threadPool = Executors.newCachedThreadPool();
for(int i = 0; i < workerCount; i++) {
    threadPool.execute(new Worker());
}

我希望我的程序/进程在所有工人完成后立即停止。但根据我的日志,再过20-30秒,这种情况才会发生。工人没有分配任何资源,事实上,他们目前什么都不做。

不要误会我的意思,这对我来说不是一个关键问题,我只是试图理解正在发生的事情,我想知道这是否是正常行为。


答案 1

Executors.newCachedThreadPool()使用 Executors.defaultThreadFactory() 作为其 .的 javadocs 说“每个新线程都是作为非守护进程线程创建的”(着重号是后加的)。因此,为 创建的线程是非守护程序。这意味着它们将阻止JVM自然退出(“自然地”我的意思是你仍然可以调用或终止程序以使JVM停止)。ThreadFactorydefaultThreadFactorynewCachedThreadPoolSystem.exit(1)

应用完成的原因是,在超时内创建的每个线程都会在一段时间不活动后自行关闭。当其中最后一个线程自行关闭时,如果您的应用程序没有任何剩余的非守护程序线程,它将退出。newCachedThreadPool

您可以(并且应该)通过关机或 手动关闭。ExecutorServiceshutdownNow

另请参阅 JavaDoc for Thread,它谈到了守护进程性。


答案 2

我希望我的程序/进程在所有工人完成后立即停止。但根据我的日志,再过20-30秒,这种情况才会发生。工人没有分配任何资源,事实上,他们目前什么都不做。

问题是您没有关闭.将所有作业提交到服务后,应关闭该服务,否则 JVM 将不会终止,除非其中的所有线程都是守护程序线程。如果不关闭线程池,那么与 关联的任何线程(如果不是守护程序)都将停止 JVM 完成。如果您已将任何任务提交到缓存的线程池,则必须等待线程超时并在 JVM 完成之前获得收获。ExecutorServiceExecutorService

ExecutorService threadPool = Executors.newCachedThreadPool();
for(int i = 0; i < workerCount; i++) {
    threadPool.execute(new Worker());
}
// you _must_ do this after submitting all of your workers
threadPool.shutdown();

将线程作为守护程序启动很可能不是您要执行的操作,因为您的应用程序可能会在任务完成之前停止,并且所有任务都将在此时立即终止。我刚刚做了一个快速的审计,在我们在生产代码中使用类的178次中,只有2次是作为守护进程线程启动的。其余的已正确关闭。ExecutorService

如果需要在应用程序退出时强制停止 ,则需要正确处理线程中断标志。ExecutorServiceshutdownNow()


推荐