在新线程上调用 运行() 和 start() 两者(!)实际上都产生了一个新线程时,两者之间的确切区别是什么?

What precisely is the difference between calling run() and start() on a new thread when both(!) actually spawn a new thread?

所以,这个问题之前已经回答过(here and here),答案对我来说完全有意义:

run() 只是调用 Thread 对象的 run() 方法,但 没有生成新线程 。因此,run() 方法中的代码实际上是在调用它的同一个线程上执行的。 另一方面,start() 将线程实例移交给调度程序并在那里调用 run(),因此它 生成一个新线程 run() 方法被执行。

但是,我很难真正理解这是什么意思,所以我开发了一个案例来验证这些说法:

public class Test extends Thread{

    public void run() {
        System.out.println("run() called on thread: " + getName());
    }

    public static void main(String[] args) throws Exception {
        System.out.println("main() called on thread: " + Thread.currentThread().getName());
        Test t = new Test();
        t.start(); // OR t.run();
    }
}

所以,如果以上是真的,程序的输出应该是如果我使用 t.run() 来执行打印语句,线程的名称应该是相同的,因为不应该创建新的线程t 只是 运行 在创建它的同一个线程上。另一方面,t.start() 实际上应该给我两个不同的线程名称。

然而,在这两种情况下我得到的输出是:

main() called on thread: main
run() called on thread: Thread-0

任何人都可以解释为什么调用 t.run() 也会产生一个新线程并且实际上不会输出:

main() called on thread: main
run() called on thread: main

您正在 Thread 对象上调用 getName(),您期望什么?当然,您将获得该 Thread 对象的名称。只有那个不是你当前操作的线程,例如:

Test t = new Test();
t.getName(); // What do you think you'll get?

我假设 Thread.currentThread().name();

会回答您想知道的问题

让我换个说法:您不是在问 "Give me the name of the current thread in which this method is running",而是在问 "Give me the name of the thread object calling this method." - 这是不一样的。

您掉进了线程 API 的一个非常常见的陷阱:无法区分 线程 Thread class. These two are completely different concepts: a thread is not even an object, it is the system resource that does the execution of your code. A Thread, on the other hand, is just a plain Java object, which happens to have some magic methods, the most magical being start() 的实例。许多其他方法只是普通的旧 Java 方法,它们与特定的 Thread 实例有关。

另一方面,

getName() is just such a method and it returns the name of this instance on which it was called. currentThread() 是一个静态方法,returns Thread 的实例负责当前 线程 。这是您要调用 getName().

的实例

在您的 Test 对象上调用 getThread returns 分配给该线程对象的名称,无论哪个线程正在执行 Test 对象的 运行 方法。

如果您修改代码以便始终获取当前线程的名称:

public class Test extends Thread{

    public void run() {
        System.out.println("run() called on thread: " + Thread.currentThread().getName());
    }

    public static void main(String[] args) throws Exception {
        System.out.println("main() called on thread: " + Thread.currentThread().getName());
        Test t = new Test();
        t.start(); // OR t.run();
    }
}

然后您会得到显示开始使用不同线程的结果:

main() called on thread: main
run() called on thread: Thread-5

和运行使用同一个线程:

main() called on thread: main
run() called on thread: main