Tob*_*oby 20 java concurrency multithreading daemon executorservice
我对按顺序关闭调度的线程的想法很满意ExectuorService; 也就是说,调用shutdown或shutdownNow将导致池上创建的线程正常退出.如果他们回复interrupt你,你可以确定最终会被调用等等,你会得到一个干净,可预测的退出(你可以清理任何资源等).
但是,如果您已将线程设置为守护程序(通过执行程序ThreadFactory),如下所示.
ExecutorService pool = Executors.newSingleThreadExecutor(new ThreadFactory() {
@Override
public Thread newThread(Runnable runnable) {
Thread thread = Executors.defaultThreadFactory().newThread(runnable);
thread.setDaemon(true);
return thread;
}
});
Run Code Online (Sandbox Code Playgroud)
主线程终止后,VM将突然终止任何守护程序线程.在上面的示例中,调度然后突然终止的(守护进程)线程将绕过任何finally块,并且任何可中断的方法都不会抛出InterruptedException.
所以,我倾向于认为,这标志着一个使用线程ThreadPoolExecutor的池守护进程是不好的做法...我的问题是真的请他帮我练声曲为什么.
为什么在ExecutorService线程池中使用守护程序线程是不好的做法(或者如果你不同意)?特别是我有兴趣通过正常关闭(具有中断策略并且运行良好的线程)与守护程序线程来描述VM关闭的生命周期.
扩展最后一点,finalizeon ThreadPoolExecutor将调用shutdown自身,但是当它使用守护程序线程时,如果finalizeVM调用它们,它们可能已经终止.那么线程池的行为是什么呢?如果底层线程突然终止,它是否可以被欺骗以保持活着(因此不会退出VM)?
我问的部分原因是因为我已经看到它曾经绕过了关闭实际的ExectorService的需要.您能想到绕过其关闭生命周期会产生不良影响的情况吗?到目前为止,我可以提出使用守护进程的唯一原因是采取捷径,我想欣赏它可能导致的任何意外的副作用.
Joo*_*kka 14
在ExecutorService的线程池中使用守护程序线程是不好的做法吗?
如果发送到该特定的任务ExecutorService可以突然终止,那么为什么不,这就是守护程序线程所做的.但通常情况下,没有很多任务可以在没有关闭仪式的情况下终止,因此如果您选择守护程序线程,您必须知道自己在做什么.
finalize()当一个对象即将被垃圾收集时调用.无论何时,如果有任何特定对象都是GCd,都不能保证,ThreadPoolExecutor也不例外,因此finalize()可以调用它,也可以不调用它.行为取决于特定的JRE实现,即使具有相同的实现,也可能随时变化.
我倾向于为守护进程和非守护进程线程使用不同的池.守护进程池往往会执行重复清理作业,监视和后台任务,如果一个或两个未执行则无关紧要.任何只在应用程序仍在运行时才有意义的任务都可以创建一个守护程序线程任务.例如,GC线程是守护程序线程.
守护程序线程可能很有用,如果它们没有突然终止,它们就不会那么有用IMO.
据推测,我们可以设想另一种类型的线程,当没有正常的线程运行时它会被中断,而不是突然终止.这可能有点方便,但如果你不得不做任何清理,你很可能想要有条不紊地清理.这将限制此功能的便利性.
另一方面,如果你有任务在关机时不需要任何清理,那么deamon线程非常方便.并且你不想浪费时间等待它们到达某个特定状态或冒着停机等问题,因为你使用deamon线程的原因是因为你不需要任何清理.如果应用程序执行任何操作将是浪费时间.正在关闭.如果你关心,那么你不应该使用deamon线程.
与deamon线程池没什么不同.如果该线程池正在执行在关闭时不需要任何清理的任务,那么由于方便起见,这将是有意义的.
来自JCiP书:
应该谨慎使用守护程序线程,可以在没有清理的情况下随时安全地放弃处理活动.特别是,将守护程序线程用于可能执行任何类型I/O的任务是危险的.守护程序线程最好保存用于"内务"任务,例如后台线程定期从内存缓存中删除过期的条目
| 归档时间: |
|
| 查看次数: |
16215 次 |
| 最近记录: |