在Java线程中,'run'方法不能抛出'checked exception'。我在Core Java(第1卷)一书中遇到过这个问题。有人可以解释背后的原因吗?
答案 0 :(得分:19)
有人可以解释背后的原因吗?
是的,因为JVM会小心忽略您在run
方法中抛出的任何异常。因此,抛出它可能是一个错误(除非你有线程的特定异常处理程序,请参阅the docs)。没有理由煽动潜在的错误行为。
或者,举个例子。
class MyThread extends Thread {
public void run() {
throw new RuntimeException();
}
}
...
new MyThread().start();
// here thread dies silently with no visible effects at all
修改强>
为什么父线程不能从生成的'子'线程'捕获'异常?
@ chaotic3quilibrium 在他的评论中已经注意到为什么不:因为父线程已经可能已经移动了。
new MyThread().start(); // launch thread and forget
// 1000 lines of code further...
i = i + 1; // would you like exception from child thread to be propagated here?
答案 1 :(得分:9)
什么会捕获异常并处理它?我们假设run方法可以抛出一个已检查的异常。然后你可以写这样的代码:
Thread myThread = new Thread(aRunnable);
try{
myThread.start();
}
catch(Exception e){
e.printStackTrace();
}
//do other stuff
但是一旦你调用myThread.start
,新线程就会在后台启动,当前线程会继续并退出try-catch并执行其他操作。因此,如果myThread
稍后再引发异常,则无法捕获它!
您需要做的是在run
方法中处理异常,然后可能有办法通知另一个对象该线程失败。
答案 2 :(得分:1)
假设线程A启动线程B.然后线程B抛出异常。您可能认为线程A捕获它会很好。但是哪里?当线程B抛出异常时,谁知道线程A正在做什么?举一个简单的例子,假设我们在线程A中有这个代码:
try
{
threadB=new PurgeAbandonedCarts();
threadB.start();
}
catch (NullPointerException panic)
{
... handle errors purging abandoned carts ...
}
try
{
processNewOrders();
}
catch (NullPointerException panic)
{
... handle problems in new orders ...
}
finally
{
... clean up ...
}
所以我们启动线程B来清除废弃的推车。一旦它开始,我们继续处理新订单。然后线程B抛出空指针异常。它应该被与线程B相关联的catch块捕获,还是与处理新订单相关联的块捕获?
如果它转到新订单捕获,那么这里的任何代码都可能与清除线程B的问题无关。这可能不是正确的答案。
如果你说与线程B关联的那个,那么这意味着在处理新订单期间,控制可能会突然被拉出并发送回尝试线程B catch块。但接下来处理新订单会发生什么?我们只是停在中间吗?我们甚至没有击中finally块?当我们完成后,我们是否继续执行并再次处理新订单?我们处理订单两次吗?这也不是正确的答案。
因此,如果run抛出异常,就无处可去。唯一合乎逻辑的做法是让run方法捕获自己抛出的任何异常,并在新线程中处理它们。
答案 3 :(得分:0)
throws
声明是方法签名的一部分。要允许Runnable#run
的已检查异常,必须在Runnable
接口上声明它们,并且每次启动线程时都必须try/catch
。
然后,我们通常不会调用run
方法,我们只是实现它。我们start()
一个线程然后以某种方式调用run
方法。
但最明显的原因是:当我们启动线程时,我们通常不希望等到run
方法终止只是为了捕获这样的异常:
try {
new Worker().start(); // now wait until run has finished
} catch (SomeThreadException oops) {
// handle checked exception
}
答案 4 :(得分:0)
原因是异常被抛回给调用者。 run()方法的调用者不是您的代码。这是Thred本身。因此,即使run()抛出异常,程序也无法捕获它。
您应该将线程执行结果放到某个类级变量中,然后从那里读取它。或者使用新的API:executors和interface Callable声明方法call(),它返回线程执行的未来结果。
答案 5 :(得分:0)
以前答案的更明显的解决方案是,如果抛出一个已检查的异常,则表示您未正确实现runnable接口中指定的run()。
它甚至不会编译:
run() in TestClass cannot implement run() in java.lang.Runnable;
overridden method does not throw java.lang.Exception