我注意到,在这个javadoc中,https://docs.oracle.com/javase/7/docs/api/java/lang/Thread.UncaughtExceptionHandler.html UncaughtExceptionHandler 用于当异常发生但未被捕获时。但是,该线程会悄悄失败吗?我想是的,因为它是异步处理其业务的,但我正在调查与我们的一个流程相关的问题,并且很惊讶现在才意识到这一点,我的职业生涯已超过 10 年了。
线程会悄悄失败:)
十多年前,有人遇到过类似的问题。随着时间的推移,系统的性能开始下降。最终,我确定了原因:某个自定义线程池中的工作线程抛出异常,并且该工作线程被终止。因此,随着时间的推移,线程池中的活动线程数量开始减少,性能下降。
问题被隐藏在没有记录异常的事实中。
[编辑]
我上面的回答不正确。下面的示例对此进行了演示:
import java.util.concurrent.TimeUnit;
public class Main {
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread(){
public void run(){
throw new RuntimeException();
}
};
t.start();
TimeUnit.SECONDS.sleep(10);
System.out.println("done");
}
}
运行代码时,将显示以下输出:
Exception in thread "Thread-0" java.lang.RuntimeException
at Main$1.run(Main.java:8)
done
因此异常已记录。
根据@pveentjar的更新答案,我运行了以下代码:
import java.util.concurrent.TimeUnit;
public class Main {
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread() {
public void run() {
throw new RuntimeException("purposeful!");
}
};
t.setUncaughtExceptionHandler((thread, throwable) -> System.out.println("uncaught: " + throwable.getMessage()));
t.start();
TimeUnit.SECONDS.sleep(10);
System.out.println("done");
}
}
,并确定 uncaughtExceptionHandler 似乎从使用它的线程中捕获了异常,允许开发人员用它做他们想做的事情,但这留下了一个问题,如果不是为了将系统从无声的失败? 输出:
uncaught: purposeful!
[a pause of approximately ten seconds]
done
我终于弄清楚了我的具体问题的根源。这是由于错误处理不当,导致线程静静地失败:
public class Main {
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread() {
public void run() {
try {
//do some stuff
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("done-worker thead");
throw new RuntimeException("purposeful!");
}
};
t.setUncaughtExceptionHandler(
(thread, throwable) -> System.out.println("main thread; uncaugh exception from worker threadt: " + throwable.getMessage()));
t.start();
TimeUnit.SECONDS.sleep(10);
System.out.println("done-main thead");
}
}
在执行“某些操作”时,应用程序遇到了 OutOfMemoryError,严格来说,这并不是一个异常。将catch语句改为
catch(Throwable t)
,解决了。