Java 当所有 ExecutorService 任务完成后,程序不会立即终止
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/20057497/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Program does not terminate immediately when all ExecutorService tasks are done
提问by alapeno
I put a bunch of runnable objects into an ExecutorService:
我将一堆可运行的对象放入 ExecutorService:
// simplified content of main method
ExecutorService threadPool = Executors.newCachedThreadPool();
for(int i = 0; i < workerCount; i++) {
threadPool.execute(new Worker());
}
I would expect my program/process to stop immediately after all workers are done. But according to my log, it takes another 20-30 seconds until that happens. The workers do not allocate any resources, in fact, they do nothing at the moment.
我希望我的程序/流程在所有工人完成后立即停止。但是根据我的日志,在发生这种情况之前还需要 20-30 秒。工人不分配任何资源,事实上,他们此刻什么都不做。
Don't get me wrong, this is not a crucial problem for me, I'm just trying to understand what is happening and I'm wondering if this is normal behavior.
不要误会我的意思,这对我来说不是一个关键问题,我只是想了解正在发生的事情,我想知道这是否是正常行为。
采纳答案by yshavit
Executors.newCachedThreadPool()
uses Executors.defaultThreadFactory()
for its ThreadFactory
. defaultThreadFactory
's javadocs say that "each new thread is created as a non-daemonthread" (emphasis added). So, the threads created for the newCachedThreadPool
are non-daemon. That means that they'll prevent the JVM from exiting naturally (by "naturally" I mean that you can still call System.exit(1)
or kill the program to cause the JVM to halt).
Executors.newCachedThreadPool()
使用Executors.defaultThreadFactory()
它的ThreadFactory
。defaultThreadFactory
的 javadocs 说“每个新线程都是作为非守护线程创建的”(强调)。因此,为它们创建的线程newCachedThreadPool
是非守护进程。这意味着它们将阻止 JVM 自然退出(“自然地”我的意思是您仍然可以调用System.exit(1)
或终止程序以导致 JVM 停止)。
The reason the app finishes at all is that each thread created within the newCachedThreadPool
times out and closes itself after some time of inactivity. When the last one of them closes itself, if your application doesn't have any non-daemon threads left, it'll quit.
应用程序完全结束的原因是每个线程在newCachedThreadPool
超时内创建并在一段时间不活动后自行关闭。当它们中的最后一个关闭时,如果您的应用程序没有任何非守护进程线程,它将退出。
You can (and should) close the ExecutorService
down manually via shutdown
or shutdownNow
.
您可以(并且应该)ExecutorService
通过shutdown
或手动关闭关闭shutdownNow
。
See also the JavaDoc for Thread, which talks about daemon-ness.
另请参阅Thread的 JavaDoc ,它讨论了守护进程。
回答by Russell Zahniser
From the javadocfor Executors.newCachedThreadPool()
:
来自javadoc的Executors.newCachedThreadPool()
:
Threads that have not been used for sixty seconds are terminated and removed from the cache.
60 秒内未使用的线程将被终止并从缓存中删除。
It is usually a good idea to call shutdown()
on an ExecutorService
if you know that no new tasks will be submitted to it. Then all tasks in the queue will complete, but the service will then shut down immediately.
它通常是一个好主意,叫shutdown()
上ExecutorService
,如果你知道,没有新的任务将被提交给它。然后队列中的所有任务都将完成,但服务将立即关闭。
(Alternately, if you don't care if all the tasks complete - for example, if they are handling background calculations that are irrelevant once your main UI is gone - then you can create a ThreadFactory
that sets all the threads in that pool to be daemon.)
(或者,如果您不关心所有任务是否完成 - 例如,如果它们正在处理在您的主 UI 消失后无关紧要的后台计算 - 那么您可以创建一个ThreadFactory
将该池中的所有线程设置为守护进程.)
回答by Gray
I would expect my program/process to stop immediately after all workers are done. But according to my log, it takes another 20-30 seconds until that happens. The workers do not allocate any resources, in fact, they do nothing at the moment.
我希望我的程序/流程在所有工人完成后立即停止。但是根据我的日志,在发生这种情况之前还需要 20-30 秒。工人不分配任何资源,事实上,他们此刻什么都不做。
The problem is that you are not shutting down your ExecutorService
. After you submit all of the jobs to the service, you should shutdown the service or the JVM will not terminate unless all of the threads in it are daemon threads. If you do not shutdown the thread-pool then any threads associated with the ExecutorService
, again if not daemon, will stop the JVM from finishing. If you've submitted any tasks to a cached thread pool then you will have to wait for the threads to timeout and get reaped before the JVM will finish.
问题是你没有关闭你的ExecutorService
. 将所有作业提交给服务后,您应该关闭该服务,否则 JVM 不会终止,除非其中的所有线程都是守护线程。如果您不关闭线程池,则任何与 相关联的线程(ExecutorService
如果不是守护程序)将阻止 JVM 完成。如果您已将任何任务提交到缓存线程池,那么您将不得不等待线程超时并在 JVM 完成之前获得收割。
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();
Starting the threads as daemon is most likely notwhat you want to do because your application may stop beforethe tasks have completed and all of the tasks will be terminated immediately at that time. I just did a quick audit and of the 178 times we use ExecutorService
classes in our production code, only 2 of them were started as daemon threads. The rest are properly shutdown.
将线程作为守护程序启动很可能不是您想要做的,因为您的应用程序可能会在任务完成之前停止并且所有任务将在那时立即终止。我刚刚做了一个快速审计,ExecutorService
在我们在生产代码中使用类的 178 次中,只有 2 次作为守护线程启动。其余均正常关机。
If you need to force an ExecutorService
to stop when the application is exiting then using shutdownNow()
with proper handling of the thread interrupt flags is in order.
如果您需要ExecutorService
在应用程序退出时强制停止,那么shutdownNow()
正确处理线程中断标志就可以了。
回答by Venkat Alugolu
For multi threading of ExecutorService Solution is threadPool.shutdown();
对于 ExecutorService 的多线程解决方案是 threadPool.shutdown();
回答by Danke Xie
Basically on an ExecutorService you call shutdown() and then awaitTermination():
基本上在 ExecutorService 上你调用 shutdown() 然后 awaitTermination():
ExecutorService taskExecutor = Executors.newFixedThreadPool(4);
while(...) {
taskExecutor.execute(new MyTask());
}
taskExecutor.shutdown();
try {
taskExecutor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
} catch (InterruptedException e) {
...
}
回答by Vsevolod Nechaev
It is due to combination keepAliveTime=60L, timeunit=TimeUnit.SECONDS and corePoolSize=0*: when thread completes task, it does not terminate immediately, it may** wait during keepAliveTime for a new task.
这是由于组合keepAliveTime=60L、timeunit=TimeUnit.SECONDS 和corePoolSize=0*:当线程完成任务时,它不会立即终止,它可能**在keepAliveTime 期间等待新任务。
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
*if core poolSize != 0 see method allowCoreThreadTimeOut() of ThreadPoolExecutor
*如果核心 poolSize != 0 参见 ThreadPoolExecutor 的方法 allowCoreThreadTimeOut()
**waiting depends on combination of current quantity of running threads in pool, corePoolSize and maximumPoolSize
**等待取决于池中当前正在运行的线程数量、corePoolSize 和 maximumPoolSize 的组合