在新线程上调用 运行() 和 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
所以,这个问题之前已经回答过(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