【问题标题】:Exception in child thread子线程中的异常
【发布时间】:2020-01-24 12:32:15
【问题描述】:

我正在使用以下内容从主线程创建一个新线程:

public static void main(String[] args) {

        try {
            new TestThread().start();
        } catch (Exception e) {
            e.printStackTrace();
        }

        System.out.println("Inside main");

    }

并抛出异常。我也可以在主线程中捕获它。但是根据article

不应该这样吧?

编辑:

public class TestThread extends Thread {

@Override
public void run() {

throw new RuntimeException();
}

 }

异常跟踪

Inside main
Exception in thread "Thread-0" java.lang.RuntimeException
    at TestThread.run(TestThread.java:8)

【问题讨论】:

  • 我们在谈论什么异常?
  • 是什么让你觉得你在主线程中抓住了它?
  • 主线程只能捕获构造函数内部或start内部发生的异常(例如,没有足够的可用内存来创建另一个线程)。您不会看到来自 run 的异常。
  • Re, "...child thread..." 知道线程 B 是由线程 A 创建的可能对有意义,但 JVM 并不关心。将线程中未捕获的异常重新抛出到“父”线程中没有意义有几个原因,但在 Java 中,其中一个原因是 JVM 甚至不会记住哪个线程是“父母。”

标签: java multithreading


【解决方案1】:

线程的run()方法抛出的异常,不会被主线程捕获,而是由JVM处理。
如果你想管理这种情况,你应该使用Thread.setUncaughtExceptionHandler 方法。

类似这样的:

class MyHandler implements Thread.UncaughtExceptionHandler
{
  @Override
  public void uncaughtException(Thread t, Throwable e)
  {
    System.out.println("Caught exception " + e.getMessage());
    e.printStackTrace();
  }
}

class MyThread extends Thread
{
  public MyThread()
  {
    setUncaughtExceptionHandler(new MyHandler());
  }

  @Override
  public void run()
  {
    throw new RuntimeException("ciao");
  }
}

【讨论】:

  • 但是我正在按照代码在 main 中捕获异常。
  • @ghostrider 不,你不是。尝试更改主线程中的异常处理程序。你会看到它没有到达那里。你现在看到的输出直接来自JVM
  • @ghostrider, Re, “我在 main... IF start() 抛出异常。但是在新线程中抛出的异常不会导致start() 抛出异常。事实上,start() 可能会返回,并且主线程可以在新线程抛出异常之前打印其消息并终止
【解决方案2】:

你参考的那篇文章是《Java Thread: Run method cannot throw checked exception》。

在 Java 中,Thread 的 run 方法不能抛出已检查的异常,因为它会涉及更改 run() 方法的签名。但是,在您的示例中,您抛出了一个RuntimeException,这不是一个检查异常。见Understanding checked vs unchecked exceptions in Java

但是请注意,您实际上并没有在主线程中捕获异常:将 printStackStrace 语句替换为 ...println("caught") 之类的语句,以便更明显。

【讨论】:

  • 但是该异常仍然不会以某种方式传播到主线程。它所要做的就是崩溃任何正在执行的线程run()
  • 是的,但是OP中提到的文章是“运行方法不能抛出检查的异常”,所以我认为问题是关于那个。
  • @SDJ,我用堆栈跟踪更新了这个问题。我想你的意思是我不会得到主线程中存在的 .start() 方法的条目吗?
  • 没有。这可以解释否决票吗?只需在你的 catch 块中添加语句 System.out.println("caught");,你就会发现你不会看到它。
猜你喜欢
  • 1970-01-01
  • 2011-02-07
  • 1970-01-01
  • 1970-01-01
  • 2011-10-15
  • 2013-02-17
  • 2022-08-05
  • 2013-12-20
  • 1970-01-01
相关资源
最近更新 更多