哪个方法调用了run()?

3
public class HelloRunnable implements Runnable {

public void run() {
    System.out.println("Hello from a thread!");
}

public static void main(String args[]) {
    (new Thread(new HelloRunnable())).start();
} } 

根据Java DocRunnable接口定义了一个方法run,该方法用于包含在线程中执行的代码。Runnable对象被传递给Thread构造函数。因此,在执行HelloRunnable时,谁调用内部的run方法呢?在Thread类中,start方法如下所示:
public synchronized void start() {
     if (threadStatus != 0)
         throw new IllegalThreadStateException();
     group.add(this);
     start0();
     if (stopBeforeStart) {
         stop0(throwableFromStop);
     }
 }

从这段代码中,我们可以看到start方法没有调用run()方法。

4
start0 方法怎么样,它会调用 run 方法吗?我的意思是,这里没有什么魔法,对吧?如果 run 被调用了,那一定是有人在调用它 :-) - Sergey Kalinichenko
什么是threadstatus?stopBeforeStart是什么意思? - Denys Kurochkin
@dasblinkenlight start0() 看起来像这样.. 内联 private native void More ...start0(); - Avik Dutta
@dasblinkenlight,一个线程的run()方法不是从start()调用内部调用的。如果线程A调用t.start(),你肯定不希望线程A调用t.run()对吧?你希望它被另一个线程调用。但是,t.start()调用发生在线程A中,并且直接或间接被start()调用的所有内容都发生在线程A中。t.run()方法会从其他地方调用。 - Solomon Slow
@dasblinkenlight,附言:如果“魔法”意味着“通过编写纯Java代码无法实现的事情”,那么是的。确实有魔法存在。对于一个纯Java程序员来说,系统调用就是一种魔法。 - Solomon Slow
1个回答

19

正如在start文档中所述:

Java虚拟机会调用此线程的run方法

因此,在JVM的start0原生代码中负责调用新创建线程中的run方法。(这并不出乎意料,因为启动线程是非常操作系统特定的,无法在纯Java中实现。)

注意start0不会直接调用run。相反(从高层次的视角上忽略JVM内部管理),它指示操作系统创建一个新线程并让该线程执行run.

为了澄清,这里简单描述一下涉及到的方法:

  • start是开始一个新的Thread的高级函数。

  • start0是一个本地方法,它从操作系统创建一个新的线程,并负责确保调用run

  • run是定义在你的Runnable类中的方法。这个方法将在新的线程中被执行。Thread对象本身并不知道它应该执行用户代码。这是相关联的Runnable对象的责任。

因此,当您调用Thread.start()时,将自动调用Runnablerun方法。

当然,您也可以显式地调用Runnablerun方法:

HelloRunnable hr = new HelloRunnable();
hr.run();

然而,这当然会在同一线程中执行,而不是在单独的线程中执行。


那么JVM是在什么时候介入的呢,比如JVM是如何被通知start()方法已经被调用,现在是时候调用run()方法了呢?@martin - Avik Dutta
好的,谢谢。 (只是好奇)那么从本地代码中调用run()方法(纯Java代码)是可能的吗? - Avik Dutta
1
我注意到你很小心地说start0“负责调用”run(),但你可以更明确地指出它并没有_调用_run()。事实上,在start()调用中根本没有从_任何地方_调用run()。它是在一个_不同的线程_中调用的。这是许多新手难以理解的概念。 - Solomon Slow

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接