Runcutable实例中的ExecutorService awaitTermination shutdown信号

时间:2016-01-07 14:36:47

标签: java multithreading executorservice

关于ExecutorService和关机过程,我有几个问题。 我的用例: 我使用ExecutorService生成固定数量的线程,其运行方法如下所示:

while (true) {
   try {
      this.currentThreadRunning = true;
      processMessage();
   }
   catch (Throwable e) {
      // Keeping the thread alive despite exceptions.
   }
}

这些线程无限运行,轮询消息。

我想做什么? 我正在轮询SQS队列以获取消息并进行处理。

显然,在我的情况下,ExecutorService's关闭方法不起作用。调用shutdownNow()时,我的所有线程都会被毫不客气地关闭。我讨厌它!

有没有办法调用awaitTermination并在我的Runnable实例中(在finally块中?)验证是否已启动shutdown并为当前线程触发相同的操作?

更新:我重构了我的代码以执行轮询,然后生成线程来处理它们。因此,Runnable实例的run方法不必是无限循环。并且awaiTermination将导致线程的明确关闭。可以肯定的是,我在shutdownNow之后触发了awaitTermination

4 个答案:

答案 0 :(得分:0)

为了无限运行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

如果我需要区分可恢复中断和关闭中断,那么我在AtomicBoolean doShutdown中共享Runnables,其初始化为false并设置为true我想要一个InterruptedException来终止线程。

答案 1 :(得分:0)

您必须检查正在运行的线程的中断状态(请参阅此处有关中断的教程: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.
        }
}

但请注意,您必须在从runnable调用的代码中正确处理中断。如果有以下内容:

try {
    // do something
} catch(InterruptedException e) {
    // ignore
}

然后这不起作用。处理InterruptedException的正确方法是致电Thread.currentThread().interrupt();

答案 2 :(得分:0)

我认为你所做的事情在概念上是错误的。

awaitTermination意味着等待所有线程自然完成然后停止执行程序。提交Runnable时,它不应该知道它的执行情况,因此,将runnable连接到执行程序并不是一个好主意恕我直言。

也许您应该查看Future课程并将Runnable实施移到那里。然后,您将被迫实施一个您可能觉得有用的cancel(boolean)方法。

您的用例是什么?也许如果您解释一下,社区可以指出更适合的实施。

答案 3 :(得分:0)

您不应该致电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/  我希望这会对你有所帮助。