我有Java主类,在类中,我开始一个新的线程,在主要的,它等待线程死亡 . 在某些时刻,我从线程中抛出一个运行时异常,但我无法捕获从主类中的线程抛出的异常 .
这是代码:
public class Test extends Thread
{
public static void main(String[] args) throws InterruptedException
{
Test t = new Test();
try
{
t.start();
t.join();
}
catch(RuntimeException e)
{
System.out.println("** RuntimeException from main");
}
System.out.println("Main stoped");
}
@Override
public void run()
{
try
{
while(true)
{
System.out.println("** Started");
sleep(2000);
throw new RuntimeException("exception from thread");
}
}
catch (RuntimeException e)
{
System.out.println("** RuntimeException from thread");
throw e;
}
catch (InterruptedException e)
{
}
}
}
谁知道为什么?
14 回答
请看看Thread.UncaughtExceptionHandler
更好(替代)的方法是使用Callable和Future来获得相同的结果......
我使用RxJava的解决方案:
如果在启动Threads的类中实现Thread.UncaughtExceptionHandler,则可以设置然后重新抛出异常:
这导致以下输出:
使用
Thread.UncaughtExceptionHandler
.目前你只捕捉
RuntimeException
,一个Exception
的子类 . 但是你的应用程序可能抛出Exception的其他子类 . 除了RuntimeException
之外,还要 grab 通用Exception
由于线程前端已经更改了许多内容,因此请使用高级java API .
首选java.util.concurrent API用于多线程,如
ExecutorService
或ThreadPoolExecutor
.您可以自定义ThreadPoolExecutor来处理异常 .
来自oracle文档页面的示例:
覆盖
示例代码:
用法:
我在上面的代码之上添加了一个构造函数:
您可以更改此构造函数以满足您对线程数的要求 .
你不能这样做,因为它没有't really make sense. If you hadn'调用
t.join()
然后当t
线程抛出异常时你的主线程可能在代码中的任何地方 .这解释了线程的状态转换,具体取决于是否发生异常:
那's because exceptions are local to a thread, and your main thread doesn' t实际上看到了
run
方法 . 我建议你阅读更多关于线程如何工作的内容,但要快速总结一下:你对start
的调用启动了一个不同的线程,完全与你的主线程无关 . 对join
的调用只是等待它完成 . 在线程中抛出并且从未捕获的异常终止它,这就是join
在主线程上返回的原因,但异常本身也会丢失 .如果您想了解这些未捕获的异常,可以尝试这样做:
有关未捕获的异常处理的更多信息,请参见here .
使用
Callable
而不是Thread,然后你可以调用Future#get()
,它会抛出Callable投掷的任何异常 .Thread中的异常处理:默认情况下,run()方法不会抛出任何异常,因此必须在那里捕获并处理run方法中的所有已检查异常,对于运行时异常,我们可以使用UncaughtExceptionHandler . UncaughtExceptionHandler是Java提供的用于处理Thread run方法中的异常的接口 . 因此,我们可以使用setUncaughtExceptionHandler()方法实现此接口并将实现类重新设置回Thread对象 . 但是这个处理程序必须在我们在脚踏上调用start()之前设置 .
如果我们不设置uncaughtExceptionHandler,则Threads ThreadGroup充当处理程序 .
在http://coder2design.com/thread-creation/#exceptions给出了很好的解释
最有可能的;
您不需要将异常从一个线程传递到另一个线程 .
如果你想处理一个异常,只需在抛出它的线程中进行 .
你的主线程根本不需要后台线程 .
但是,假设您确实需要处理子线程中的异常 . 我会像这样使用ExecutorService:
版画
您是否使用过setDefaultUncaughtExceptionHandler()和Thread类的相似方法?从API:“通过设置默认的未捕获异常处理程序,应用程序可以更改已经接受任何”默认“行为的线程处理未捕获异常的方式(例如,记录到特定设备或文件)系统提供 . “
你可能会找到你问题的答案......祝你好运! :-)
我遇到了同样的问题......很少解决(只针对实现而不是匿名对象)...我们可以将类级异常对象声明为null ...然后在catch块中为run方法初始化它...如果有在run方法中是错误的,这个变量不会为null ..然后我们可以对这个特定的变量进行空检查,如果它不为null,那么在线程执行中就有异常 .
在join()之后调用checkForException()
扩展
Thread
几乎总是错误的 . 我不能强烈地说明这一点 .多线程规则#1:扩展线程错误 . *
如果您实施
Runnable
,您将看到您的预期行为 .产生;
*除非您想要更改应用程序使用线程的方式,否则99.9%的情况下您不会 . 如果您认为自己处于0.1%的情况,请参阅规则#1 .