正在捕获 Java Throwable 重启线程的最佳方式

Is catching Java Throwable best way to restart thread

我在 java-

中有以下代码
@Override
public void run() {

    logger.info("Thread Started:" + this.getName());

    try {
        runJob();
    } catch( Throwable e) {
        logger.error("Exception in running thread: " + this.getName() + ", restarting job", e);
        run();
    }
}

public void runJob() {

    while(true) {
       try {
           // Work here
       } catch(Exception e) {
           // log the exception
       }
    }
 }

这段代码实际上是要让线程在任何情况下都保持活动状态吗?这是恢复线程的唯一方法吗?

这是我看完所有答案后想到的备选方案。让我知道这是否是即使发生错误也能使线程永远保持活动状态的好方法:

@Override
public void run() {

    logger.info("Thread Started:" + this.getName());

    while(true) {
      try {
        runJob();
      } catch( Throwable e) {
        logger.error("Exception in running thread: " + this.getName() + ", restarting job", e);
        }
    }
}

public void runJob() {

     try {
          // Work here
     } catch(Exception e) {
          // log the exception
     }
 }

你永远不应该用 try-catch 来控制流量!

此外,如果你在catch中调用这个失败的方法,它将被再次调用,导致递归无休止的循环,因此WhosebugError

我建议您创建一个计数器来限制最大尝试次数。 对于此用例,请从问题 How do you implement a re-try-catch?

中获得灵感

有很多库提供恢复机制。我推荐你 jcabi-aspects.

它不会 'recover' 它而是重新开始并重试。这会导致无限循环的递归调用,直到发生 Whosebug。在这种情况下,您的应用程序无论如何都会停止。

想象一下访问一个不存在的文件(由于拼写错误或其他原因)。您总是会遇到 FileNotFoundException 并重新开始尝试一次又一次地读取同一个不存在的文件...

一遍又一遍地开始相同的任务而不做任何更改几乎总是会导致相同的异常和上述情况happens.A正确的异常处理总是比让你的程序保持活力更重要任何情况。让您的软件用户知道问题所在。也许这是他可以改变的事情。也许不吧。在任何情况下,最好中止线程而不是递归地重新开始。

这与"threads"关系不大。可以在异常情况下实现重试逻辑,这是常见的做法。

然而,抓住 Throwable 显然是一件危险的事情。您可能希望在 select 错误(例如超时、连接失败等)时重试,这当然需要更好地了解您的 runJob() 方法如何运行。

除此之外,您的重试实现正在进行 递归 调用,这也可能是错误的。你最终会 运行 进入堆栈溢出错误(并且 catch 它与你的 Throwbale catch 块一起导致奇怪的行为)。而是循环并重复执行 runJob()

boolean retry = false;
do {
    try {
        runJob();
        retry = false;
    } catch (SpecificException e) { //timeout, network failure exceptions
        logger.error("Exception in running thread: "
            + this.getName() + ", restarting job");
        retry = true;
    }
} while(retry);

您可能还需要添加一个计数器来限制重试次数。