Java Thread:Run方法不能抛出已检查的exception

在Java线程中,’run’方法不能抛出’checked exception’。 我在Core Java(第1卷)一书中遇到过这个问题。 有人可以解释背后的推理吗?

有人可以解释背后的推理吗?

是的,因为JVM会小心忽略您在run方法中抛出的任何exception。 因此,抛出它可能是一个错误(除非你有线程的特定exception处理程序,请参阅有关该文档的文档 )。 没有理由煽动潜在的错误行为。

或者,举个例子。

  class MyThread extends Thread { public void run() { throw new RuntimeException(); } } ... new MyThread().start(); // here thread dies silently with no visible effects at all 

编辑

为什么父线程不能从生成的’子’线程’捕获’exception?

@ 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? 

什么会捕获exception并处理它? 我们假设run方法可以抛出一个已检查的exception。 然后你可以写这样的代码:

 Thread myThread = new Thread(aRunnable); try{ myThread.start(); } catch(Exception e){ e.printStackTrace(); } //do other stuff 

但是一旦你调用myThread.start ,新的线程就会在后台启动,当前线程会继续并退出try-catch并执行其他操作。 所以如果myThread确实抛出exception,你就无法抓住它!

您需要做的是在run方法中处理exception,然后可能有办法通知另一个对象该线程失败。

假设线程A启动线程B.然后线程B抛出exception。 您可能认为线程A捕获它会很好。 但是哪里? 当线程B抛出exception时,谁知道线程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抛出空指针exception。 它应该被与线程B关联的catch块捕获,还是与处理新订单相关联的块捕获?

如果它转到新订单catch,那么这里的任何代码都可能与清除线程B的问题无关。这可能不是正确的答案。

如果你说与线程B相关联的那个,那么这意味着在处理新订单期间,控制可能会突然被拉出并发送回来尝试线程B catch块。 但接下来处理新订单会发生什么? 我们只是停在中间吗? 我们甚至没有击中finally块? 当我们完成后,我们是否继续执行并再次处理新订单? 我们处理订单两次吗? 这也不是正确的答案。

因此,如果run抛出exception,就无处可去。 唯一合乎逻辑的做法是让run方法捕获自己抛出的任何exception,并在新线程中处理它们。

throws声明是方法签名的一部分。 要允许Runnable#run检查exception,必须在Runnable接口上声明它们,并且每次启动线程时都必须try/catch

然后,我们通常不会调用run方法,我们只是实现它。 我们start()一个Thread,然后以某种方式调用run方法。

但最明显的原因是:当我们启动线程时,我们通常不希望等到run方法终止只是为了捕获这样的exception:

 try { new Worker().start(); // now wait until run has finished } catch (SomeThreadException oops) { // handle checked exception } 

原因是exception被抛回调用者。 run()方法的调用者不是您的代码。 这是Thred本身。 所以即使run()抛出exception,程序也无法捕获它。

您应该将线程执行结果放到某个类级变量中,然后从那里读取它。 或者使用新的API:executors和接口Callable声明方法call(),它返回线程执行的未来结果。

之前答案的更明显的解决方案是,如果抛出一个已检查的exception,则表示您未正确实现runnable接口中指定的run()。

它甚至不会编译:

 run() in TestClass cannot implement run() in java.lang.Runnable; overridden method does not throw java.lang.Exception