run()
与 start()
方法的区别详解
在 Java 多线程编程中,线程的启动通常通过 Thread
类的 start()
方法来实现,而 run()
方法则是线程执行的实际逻辑。理解这两个方法的区别,对于掌握线程的正确使用至关重要。本文将深入探讨 run()
和 start()
方法的核心区别,分析其背后的执行机制,并附上详细解释和示例代码。
1. run()
方法概述
run()
方法是线程执行的任务体。它定义了线程启动后要执行的代码逻辑。run()
方法本身只是一个普通的方法,调用它不会启动新的线程,而是会在当前线程中执行。
- 作用:提供线程执行的任务逻辑。
- 执行位置:由线程启动后由 JVM 调用,或者由开发者直接调用。
2. start()
方法概述
start()
方法是线程启动的关键方法。调用 start()
方法会创建一个新的线程,并将线程状态由“新建”(New)转换为“就绪”(Runnable)状态。然后,JVM 会调用 run()
方法来执行线程任务。
- 作用:启动一个新的线程,调用
run()
方法。 - 执行位置:在调用
start()
后,JVM 自动启动新线程。
3. run()
与 start()
的区别分析
特性 | run() 方法 | start() 方法 |
---|---|---|
功能 | 定义线程执行的任务,但仅在当前线程执行。 | 启动一个新线程并调用 run() 方法执行线程任务。 |
调用时机 | 在任何地方直接调用,都会在当前线程中执行。 | 只能通过调用 Thread 对象的 start() 方法启动新线程。 |
线程状态 | 不会改变线程的状态,仅是当前线程中的一个方法调用。 | 启动新线程并将线程状态从“新建”转换为“就绪”。 |
影响 | 不会创建新线程,仅在当前线程执行任务。 | 创建一个新线程,并由 JVM 调度执行 run() 方法。 |
阻塞与否 | 直接调用 run() 会阻塞当前线程,执行完成后才返回。 | start() 方法不会阻塞当前线程,run() 在新线程中执行。 |
4. 代码示例及分析
示例 1:直接调用 run()
方法
class MyThread extends Thread {
@Override
public void run() {
System.out.println("Thread is running");
}
}
public class Main {
public static void main(String[] args) {
MyThread thread = new MyThread();
thread.run(); // 直接调用run()方法
System.out.println("Main thread");
}
}
输出:
Thread is running
Main thread
- 分析:此处直接调用
run()
方法并没有启动新的线程,而是直接在当前主线程中执行了run()
方法中的代码。结果就是run()
中的任务与主线程的输出混合在一起。
示例 2:使用 start()
方法启动线程
class MyThread extends Thread {
@Override
public void run() {
System.out.println("Thread is running");
}
}
public class Main {
public static void main(String[] args) {
MyThread thread = new MyThread();
thread.start(); // 使用start()方法启动线程
System.out.println("Main thread");
}
}
输出:
Main thread
Thread is running
- 分析:通过调用
start()
方法,创建了一个新线程,并开始执行run()
方法中的任务。可以看到,主线程输出Main thread
后,新线程输出Thread is running
,两个输出结果顺序可能不同,表明线程是并行执行的。
5. start()
方法的工作原理
当调用 start()
方法时,JVM 会:
- 创建一个新的线程。
- 调用该线程的
run()
方法。 - 将新线程加入到线程调度队列中,由操作系统调度器控制该线程的执行。
6. 错误示例:不调用 start()
方法
如果直接调用 run()
方法而不是 start()
方法,程序会在当前线程中执行 run()
,并不会启动新的线程。这种做法没有多线程的效果,违背了多线程编程的初衷。
// 错误做法,不使用start()
MyThread thread = new MyThread();
thread.run(); // 直接调用run(),没有启动新线程
7. 总结
run()
是线程的任务定义方法,直接调用不会启动新线程,而是在当前线程中执行。start()
是启动线程的方法,调用后会启动一个新线程并执行run()
方法中的代码。
通过合理使用 start()
和 run()
方法,可以高效地管理和执行多线程任务。在编写多线程程序时,正确理解和区分这两个方法的功能,能避免不必要的错误并提升代码的执行效率。