start 方法和 run 方法的主要区别是什么?
参考回答
在 Java 中,start()
和 run()
方法都与线程的启动相关,但它们有明显的区别:
start()
方法:- 用于启动一个新线程,真正创建一个新的执行路径(即新线程)。
- 调用
start()
后,JVM 会调用线程的run()
方法,并由系统调度该线程运行。
run()
方法:- 只是线程的一个普通方法,直接调用时并不会启动新线程,而是在当前线程中以普通方法的方式执行。
关键区别:
start()
方法会创建新线程并执行run()
方法。- 直接调用
run()
方法不会创建新线程,run()
方法的逻辑会在当前线程中执行。
详细讲解与拓展
1. start()
方法的行为
调用 start()
方法会触发以下流程:
- 创建新线程并分配系统资源。
- 将线程状态从 NEW(新建) 改为 RUNNABLE(就绪)。
- JVM 调用线程的
run()
方法,开始执行线程任务。
示例:
public class StartExample {
public static void main(String[] args) {
Thread thread = new Thread(() -> System.out.println("Running in a new thread!"));
thread.start(); // 启动一个新线程
System.out.println("Main thread is running!");
}
}
输出可能为:
Main thread is running!
Running in a new thread!
这里主线程和新线程并发执行,顺序可能不确定。
2. run()
方法的行为
如果直接调用 run()
方法:
- 线程不会启动新执行路径。
run()
方法的代码将在当前线程中执行,与普通方法调用无异。
示例:
public class RunExample {
public static void main(String[] args) {
Thread thread = new Thread(() -> System.out.println("Running in the current thread!"));
thread.run(); // 直接调用 run 方法
System.out.println("Main thread is running!");
}
}
输出顺序一定是:
Running in the current thread!
Main thread is running!
因为这里的 run()
方法在主线程中同步执行,没有并发。
3. 总结区别
方法 | 行为 | 是否创建新线程 |
---|---|---|
start() |
启动一个新线程,并调用 run() 方法。 |
是 |
run() |
在当前线程中执行 run() 方法的逻辑,与普通方法调用无异。 |
否 |
4. 常见误区
误区 1:直接调用 run()
可以启动线程
- 实际上,直接调用
run()
只是一个普通方法调用,不会创建新线程。
示例:
Thread thread = new Thread(() -> System.out.println(Thread.currentThread().getName()));
thread.run(); // 输出 "main"
thread.start(); // 输出 "Thread-0"
误区 2:调用 start()
后线程立即执行
start()
只是让线程进入就绪状态(RUNNABLE),具体什么时候执行由操作系统调度决定。
5. 注意事项
start()
方法只能调用一次: 如果尝试多次调用start()
,会抛出IllegalThreadStateException
。Thread thread = new Thread(() -> {}); thread.start(); // 第一次调用,正常 thread.start(); // 第二次调用,抛出异常
run()
方法可以多次调用: 因为它是普通方法,但不会创建新线程。
6. 拓展知识
start()
和 run()
的底层实现
-
start()
:- 调用的是本地方法
start0()
,通过操作系统分配资源,真正启动线程。 -
源码片段(JDK 8):
public synchronized void start() { if (threadStatus != 0) throw new IllegalThreadStateException(); group.add(this); start0(); // 本地方法,启动线程 }
- 调用的是本地方法
-
run()
:- 是线程执行任务的逻辑代码。
- 如果直接调用,程序只是在当前线程中顺序执行,没有多线程特性。
7. 什么时候直接使用 run()
?
尽管在大多数场景中我们使用 start()
方法启动新线程,但在某些测试或单线程模拟场景下,可以直接调用 run()
:
- 用于测试线程任务的逻辑,而无需创建线程。
- 用于无需多线程执行的简单任务。
8. 小结
start()
: 启动新线程,让线程独立运行。run()
: 普通方法调用,在当前线程中执行。