我有几个关于ExecutorService
和关机过程的问题。我的用例:我使用ExecutorService
生成固定数量的线程,其运行方法如下所示:
while (true) {
try {
this.currentThreadRunning = true;
processMessage();
}
catch (Throwable e) {
// Keeping the thread alive despite exceptions.
}
}
这些线程无限运行,轮询消息。
我想做什么?我正在轮询 SQS 队列中的消息并处理它们。
显然,就我而言,ExecutorService's
关闭方法不起作用。当调用shutdownNow()
时,我的所有线程都会毫不客气地关闭。我讨厌它!
有没有办法在我的Runnable
实例中调用awaitTermination
并验证是否已启动关闭并为当前线程触发相同的关闭?
更新:我重构了我的代码以执行轮询,然后生成线程来处理它们。因此,Runnable 实例的 run 方法不必是无限循环。awaiTermination
将导致线程的明确闭合。可以肯定的是,我已经触发了shutdownNow
awaitTermination
.
我认为你正在做的事情在概念上是错误的。
awaitTermination
旨在等待所有线程自然完成,然后停止执行程序。提交Runnable
时,它不应该知道它的执行上下文,因此,恕我直言,将您的可运行对象与执行器耦合不是一个好主意。
也许您应该查看Future
类并将Runnable
实现移到那里。然后,您将被迫实现一种您可能会发现有用的cancel(boolean)
方法。
您的用例到底是什么?也许如果你解释一下,社区可以指出一个更合适的实现。
对于无限运行的Runnables
,我依赖于捕获一个InterruptedException
,它通常会从我的调用shutdownNow()
或偶尔从调用Future#cancel(true)
中抛出
while(!Thread.interrupted()) {
try {
} catch(InterruptedException e) {
break;
} catch(Throwable e) {
// Keeping the thread alive despite exception
}
}
// Thread was interrupted via shutdownNow(), cleanup resources
如果我需要区分可恢复中断和关闭中断,那么我会在我的Runnables
中共享一个AtomicBoolean doShutdown
,该初始化为 false
,如果我希望InterruptedException
终止线程,则设置为 true
。
您必须检查正在运行的线程的中断状态(请参阅此处的中断教程:https://docs.oracle.com/javase/tutorial/essential/concurrency/interrupt.html(。您的代码应该是:
while (!Thread.currentThread().isInterrupted()) {
try {
this.currentThreadRunning = true;
processMessage();
}
catch (Throwable e) {
// Keeping the thread alive despite exceptions.
}
}
但请注意,您必须在从可运行对象调用的代码中正确处理中断。如果有类似以下内容的内容:
try {
// do something
} catch(InterruptedException e) {
// ignore
}
那么这行不通。处理InterruptedException
的正确方法是调用Thread.currentThread().interrupt();
。
你不应该调用shutdownNow()
但你应该只调用关闭并使用awaitTermination
等待一段时间。
所以关闭将是这样的
声明一个易失变量
private volatile stopThread = false;
关机时,您呼叫
this.stopThread = true;
executor.shutdown();
executor.awaitTermination(..
executor.shutdownNow() // in case termination takes too long
在线程中,您检查 stopThread 变量。您不能在此处使用 isInterrupted,因为我们没有中断线程。我们只是根据这种情况等待线程退出
if(stopThread){
// calling off all the operations and returning
}
我写了一篇关于正确关闭执行器服务的文章http://programtalk.com/java/executorservice-not-shutting-down/我希望这对你有帮助。