【发布时间】:2011-10-03 12:02:37
【问题描述】:
假设一个线程是从 main 方法启动的。如果在线程中抛出异常但在线程内没有处理,会发生什么?
是否可以将异常传播回主方法?
【问题讨论】:
标签: java multithreading exception
假设一个线程是从 main 方法启动的。如果在线程中抛出异常但在线程内没有处理,会发生什么?
是否可以将异常传播回主方法?
【问题讨论】:
标签: java multithreading exception
我们谈论的是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。
【讨论】:
如果异常被该线程中运行的代码捕获并处理,那么它将被处理,但是会写入 catch 块逻辑。对于这个答案的其余部分,我将假设您在谈论未捕获的异常。
未捕获的异常将导致线程退出。当它冒泡到Thread.run() 的顶部时,它将由线程的UncaughtExceptionHandler 处理。默认情况下,这只会将堆栈跟踪打印到控制台。线程本身将在此时退出 - 无论如何它都无法真正继续,因为它的 run() 方法已经完成。
因此,如果您希望在主线程中重新引发异常,您可以定义一个 UncaughtExceptionHandler 来执行此操作(这是一个非常简单的接口),然后在创建后在生成的线程上调用 Thread.setUncaughtExceptionHandler,传入您的自定义异常处理程序。
编写处理程序的唯一可能棘手的部分是确定您将在何处以及如何准确地将可投掷物“插入”到主线程中。这并不完全明显,如果您的线程正在做其他事情,并且很大程度上取决于您如何设计您的应用程序以及它的并发支持是什么样的。
(另一方面,如果您的主线程只是在等待另一个线程运行,那么它会变得更容易。但在这种情况下,也许您的主线程应该将任务提交给线程ExecutorService 并阻塞在Future 上,它将为您处理所有这些布线/生命周期的东西?)
【讨论】:
不,它不能。仔细想想,main() 方法可能在几天前就完成了。
来自线程的任何未捕获的异常都会传播到线程的UncaughtExceptionHandler。如果未定义,则转到线程组的处理程序,如果也未设置,则转到默认处理程序。
【讨论】:
days ago 的回答中的第一行有助于更好地理解该问题。实际上,多个线程可以像碰巧(轻松)共享数据的单独进程一样运行。可以使用单独的进程和共享内存构建完全相同的模型(有些困难)。
如果异常没有被try {} catch (Exception e){} 处理,那么它会被引发并抛出给调用的函数。
如果它是单独的独立线程,则不能将其传播到不是线程父对象的对象
或其他一些信息:How to throw a checked exception from a java thread?
【讨论】:
通常,如果您不自己实现异常,当发生异常时,它会关闭执行。
【讨论】:
异常被UncaughtExceptionHandler 捕获。如果你愿意,你可以在那里捕获它并将其传播回主线程。
【讨论】: