java 线程异常

2022-09-01 20:23:36

假设一个线程是从 main 方法启动的。如果在线程中引发异常,但在线程中未处理,会发生什么情况?

是否可以将异常传播回 main 方法?


答案 1

我们谈论的是方法中引发的未经检查的异常。默认情况下,您将在系统错误中得到如下sth:Thread.run

Exception in thread "Thread-0" java.lang.RuntimeException
    at Main$1.run(Main.java:11)
    at java.lang.Thread.run(Thread.java:619)

这是 printStackTrace 对于未处理的异常的结果。要处理它,您可以添加自己的UncaughtExceptionHandler:

   Thread t = new Thread(new Runnable(){
        public void run() {
            throw new RuntimeException();
        }       
    });
   t.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {

        public void uncaughtException(Thread t, Throwable e) {
            System.out.println("exception " + e + " from thread " + t);
        }
    });
    t.start();

要为所有线程设置处理程序,请使用静态方法 。Thread.setDefaultUncaughtExceptionHandler


答案 2

如果异常被该线程中运行的代码捕获并处理,则无论编写块逻辑如何,都将对其进行处理。我将假设在这个答案的其余部分,你说的是未捕获的异常。catch

未捕获的异常将导致线程退出。当它冒泡到顶部时,将由线程的UncaughtExceptionHandler处理。默认情况下,这只会将堆栈跟踪输出到控制台。线程本身将在此时退出 - 它无论如何都无法真正继续,因为它的方法已经完成了。Thread.run()run()

因此,如果您希望在主线程中重新提取异常,则可以定义一个 UncaughtExceptionHandler 来执行此操作(这是一个非常简单的接口),然后在创建生成的线程后调用它,并传入自定义异常处理程序。Thread.setUncaughtExceptionHandler


编写处理程序的唯一可能棘手的部分是确定要将可抛出物“插入”主线程的位置和方式。如果您的线程正在执行其他操作,这并不完全明显,并且很大程度上取决于您如何设计应用程序及其并发支持的样子。

(另一方面,如果您的主线程只是在等待另一个线程运行,那么它变得更容易。但是在这种情况下,也许你的主线程应该将任务提交给线程并阻塞,这将为你处理所有这些连接/生命周期的东西?ExecutorServiceFuture