正在捕获 Java Throwable 重新启动线程的最佳方法



我在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
}
}

这与"线程"关系不大。重试逻辑可以在异常上实现,这是常见的做法。

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

除此之外,您的重试实现正在进行递归调用,这也可能是不好的。您最终会遇到堆栈溢出错误(并且还会用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);

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

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

而且,如果你在catch中调用这个失败的方法,它将再次调用,导致递归永无止境的循环,从而StackOverflowError

我建议您创建一个计数器来限制最大尝试次数。 对于此用例,请从如何实现重试捕获的问题中获得灵感?

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

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

想象一下,访问一个不存在的文件(由于拼写错误或其他原因(。你总是会抓住一个FileNotFoundException,然后重新开始尝试一次又一次地读取同一个不存在的文件......

一遍又一遍地开始相同的任务而不改变任何内容几乎总是会导致相同的异常,并且会发生上述情况。在任何情况下,正确的异常处理始终比保持程序正常运行更重要。让软件用户知道问题所在。也许这是他可以改变的。也许不是。无论如何,最好中止线程,而不是递归重新开始。

最新更新