工作线程发出应该启动正常关闭的最佳方式是什么?
我有一个固定大小的线程池,它通过一组连续的任务工作,每个任务持续不超过几秒钟。在正常操作期间,这种方法很好,并且随着工作量的增加而突出。
我遇到的问题是在其中一个线程中抛出异常。如果发生这种情况,我想把整个事情搞砸,并且无法正常工作。
我一直使用的天真方法是在“Supervisor”类中使用静态方法,该方法使用标准shutdown()
和awaitTermination()
方法关闭线程池。如果遇到问题,则由任何“Worker”类调用它。完成此操作而不是传播异常,因为execute()
需要Runnable
而run()
方法不能抛出异常。
这是一些伪代码:
// Finds work to do and passes them on to workers
class Supervisor {
ThreadPoolExecutor exec;
static main() {
exec = new FixedThreadPool(...);
forever {
exec.execute(new Worker(next available task));
}
}
static stopThreadPool() {
exec.shutdown();
if(!exec.awaitTermination(timeout_value)) {
print "Timed out waiting on terminate"
}
}
}
class Worker {
run() {
try {
// Work goes here
} catch () {
Supervisor.stopThreadPool()
}
}
}
我看到的效果是线程暂停了一段时间,但后来我看到了超时消息,他们都恢复了处理。这种模式一直持续到我手动关闭它为止。如果在断开循环后在main方法中调用stopThreadPool()
,则按预期正确关闭。
这种方法显然是错误的,因为它不起作用,但它也感觉就像设计不对。
重申一个问题:工作线程发出应该启动正常关闭的最佳方式是什么?
我在SO上看到的问题有两种类型:
那不是我追求的。他们似乎也只谈论一组有限的任务,而我正在处理一个连续的饲料。
我已经阅读过使用exec.submit()
和Future
的另一种方法,它将责任放在主管类上以检查一切是否正常,但我不知道它是否知道它是否是一个更好的设计。例外情况是,例外情况,所以我不想在不必要的情况下为正常情况添加工作/复杂性。
(小方注意:这是一个工作项目,还有其他人参与。为简单起见,我在问题中说“我”。)
答案 0 :(得分:4)
您距离正确的解决方案还不远,问题是您需要正确处理由关闭调用引起的中断。所以你的线程的run方法应如下所示:
run () {
try {
while (Thread.interrupted() == false) {
doSomeWork();
}
} catch (Exception e) {
myExecutor.shutdown();
}
}
请注意,我明确地使用了shutdown()
而没有awaitTermination()
,否则等待线程会使Executor无法正常终止,因为一个线程仍在等待。完美的单线程死锁。 ;)
中断检查是关于如何正常杀死线程的提示:通过将running
布尔值设置为false或通过中断来使run方法结束,线程将在片刻之后死亡
要检查所有线程是否已终止(=即将结束其运行方法),您可以将CountDownLatch用于简单的情况,或使用CyclicBarrier / Phaser类来处理更复杂的情况。
答案 1 :(得分:1)
这里有两个问题:
如果您只想强制关闭工作程序中的任何异常,那么您可以使用shutdown()并等待对应方。只需使用shutdownNow强制它,你应该很好。关机会正常关机。
尝试在发生这样的事情时打破你的for循环。最好的方法是在执行调用的for循环中使用try catch。当一个工程中发生异常时抛出一个未经检查的异常并在for循环中捕获它。终止for循环并调用您的方法强制关闭执行程序。这是一种更清洁的方法。或者,您也可以考虑使用执行程序中的处理程序来执行此操作。