Runnable 实例中的 ExecutorService awaitTermination 关闭信号
ExecutorService awaitTermination shutdown signal in the Runnable instance
我有几个关于 ExecutorService
和关闭过程的问题。
我的用例:
我使用 ExecutorService
生成固定数量的线程,其 运行 方法如下所示:
while (true) {
try {
this.currentThreadRunning = true;
processMessage();
}
catch (Throwable e) {
// Keeping the thread alive despite exceptions.
}
}
这些线程 运行 无限,轮询消息。
我想做什么?
我正在为消息轮询 SQS 队列并处理它们。
显然,在我的例子中,ExecutorService's
关闭方法不起作用。当 shutdownNow()
被调用时,我所有的线程都被毫不客气地关闭了。我恨它!
有没有办法在我的 Runnable
实例中(在 finally 块中?)调用 awaitTermination
并验证是否已启动关闭并为当前线程触发相同的关闭?
更新:我重构了我的代码以执行轮询,然后生成线程来处理它们。因此,Runnable 实例的 运行 方法不必是无限循环。 awaiTermination
将导致线程的明确关闭。可以肯定的是,我在 awaitTermination
.
之后触发了 shutdownNow
对于无限 运行 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
并设置为 true
如果我想要一个 InterruptedException
来终止线程。
您必须检查您 运行 所在的线程的中断状态(请参阅此处的中断教程: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();
.
我认为你所做的在概念上是错误的。
awaitTermination
的意思是等待所有线程自然结束,然后停止执行器。提交 Runnable
时,它不应该知道它的执行上下文,因此,恕我直言,将你的可运行对象与你的执行程序耦合并不是一个好主意。
也许您应该查看 Future
class 并将您的 Runnable
实施移到那里。然后你将被迫实施一个你可能会觉得有用的 cancel(boolean)
方法。
您的具体用例是什么?也许如果你解释一下,社区可以指出一个更合适的实现。
你不应该调用 shutdownNow()
但你应该只调用 shutdown 并使用 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
}
我写过一篇关于正确关闭executorservice的文章
http://programtalk.com/java/executorservice-not-shutting-down/
希望对您有所帮助。
我有几个关于 ExecutorService
和关闭过程的问题。
我的用例:
我使用 ExecutorService
生成固定数量的线程,其 运行 方法如下所示:
while (true) {
try {
this.currentThreadRunning = true;
processMessage();
}
catch (Throwable e) {
// Keeping the thread alive despite exceptions.
}
}
这些线程 运行 无限,轮询消息。
我想做什么? 我正在为消息轮询 SQS 队列并处理它们。
显然,在我的例子中,ExecutorService's
关闭方法不起作用。当 shutdownNow()
被调用时,我所有的线程都被毫不客气地关闭了。我恨它!
有没有办法在我的 Runnable
实例中(在 finally 块中?)调用 awaitTermination
并验证是否已启动关闭并为当前线程触发相同的关闭?
更新:我重构了我的代码以执行轮询,然后生成线程来处理它们。因此,Runnable 实例的 运行 方法不必是无限循环。 awaiTermination
将导致线程的明确关闭。可以肯定的是,我在 awaitTermination
.
shutdownNow
对于无限 运行 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
并设置为 true
如果我想要一个 InterruptedException
来终止线程。
您必须检查您 运行 所在的线程的中断状态(请参阅此处的中断教程: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();
.
我认为你所做的在概念上是错误的。
awaitTermination
的意思是等待所有线程自然结束,然后停止执行器。提交 Runnable
时,它不应该知道它的执行上下文,因此,恕我直言,将你的可运行对象与你的执行程序耦合并不是一个好主意。
也许您应该查看 Future
class 并将您的 Runnable
实施移到那里。然后你将被迫实施一个你可能会觉得有用的 cancel(boolean)
方法。
您的具体用例是什么?也许如果你解释一下,社区可以指出一个更合适的实现。
你不应该调用 shutdownNow()
但你应该只调用 shutdown 并使用 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
}
我写过一篇关于正确关闭executorservice的文章 http://programtalk.com/java/executorservice-not-shutting-down/ 希望对您有所帮助。