如果 main() 方法是通过线程启动的,为什么 run() 不显示在调用层次结构的顶部?
正如其他人所提到的,这是因为“主”线程是特殊的。它不是通过标准Thread
类机制启动的,而是通过 Java 引导代码启动的。public static void main(String[] args)
始终由本机代码的主线程运行。
另一种解释是,实际上可能存在一种run()
方法,但他们构建堆栈帧的方式是故意隐藏它,以免混淆用户。例如,由于您正在执行 anew Thread(new Test())
那么您的Test
类实际上target
是Thread
. 当后台Thread
启动时,它实际上调用Thread.run()
了代码:
public void run() {
if (target != null) {
target.run();
}
}
但是我们从未在堆栈帧中看到该Thread.run()
方法,尽管它似乎应该在那里。如果用户在超类中覆盖该方法,则该run()
方法将Thread
位于堆栈帧中。它可以被 JDK 删除以改善堆栈帧输出。
Java 中的多线程是通过定义 run() 和调用 start() 来完成的。
这是正确的,但对于后代来说,我认为意识到你的代码有问题很重要。您的Test
课程不应扩展,Thread
而应实施Runnable
。它之所以有效,是因为Thread
实现了Runnable
.
您应该实现Runnable
并将代码更改为如下所示:
public class Test implements Runnable {
public static void main(String[] args) throws Exception {
new Thread(new Test()).start();
throw new RuntimeException("Exception from main thread");
}
public void run() {
throw new RuntimeException("Exception from child thread");
}
}
或者您仍然扩展Thread
并更改启动线程的方式,如下所示。推荐使用上述Runnable
模式,因为它允许您的Test
线程在必要时扩展另一个类。
public class Test extends Thread {
public static void main(String[] args) throws Exception {
new Test().start();
throw new RuntimeException("Exception from main thread");
}
@Override
public void run() {
throw new RuntimeException("Exception from child thread");
}
}
为什么这很重要?您当前的代码实际上是实例化 2 个Thread
对象,但其中只有一个是start()
ed 并且作为 background 运行Thread
。您可能会遇到以下错误:
public class Test extends Thread {
public static void main(String[] args) throws Exception {
Test test = new Test();
new Thread(test).start();
// this is not interrupting the background thread
test.interrupt();