执行程序服务等待可运行实例中的终止关闭信号



我有几个关于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/我希望这对你有帮助。

最新更新