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(): 普通方法调用,在当前线程中执行。