直接调用 run() 方法无法启动新线程,因为它只是普通的方法调用,会在当前线程中同步执行,导致程序阻塞且无法利用多线程优势。要真正启动线程,必须调用 start() 方法,该方法会通知 jvm 创建新的操作系统级线程并调度执行 run() 逻辑。

直接调用 run 方法的实际执行效果是什么
直接调用 run() 时,代码在当前主线程中顺序执行,没有产生并发。这意味着耗时操作会阻塞主线程,后续代码必须等待 run() 执行完毕才能运行。这种行为等同于调用任何普通的实例方法,完全失去了多线程的意义。
public class DirectRunDemo {
public static void main(String[] args) {
MyThread thread = new MyThread();
System.out.println("Before run: " + Thread.currentThread().getName());
thread.run(); // 直接调用
System.out.println("After run: " + Thread.currentThread().getName());
}
}
class MyThread extends Thread {
@Override
public void run() {
System.out.println("Inside run: " + Thread.currentThread().getName());
}
}预期输出:
Before run: main Inside run: main After run: main
可以看到,所有输出都来自 main 线程。这证明了直接调用 run() 并没有创建新线程,而是直接在主线程中执行了任务逻辑。
立即学习“Java免费学习笔记(深入)”;
调用 start 方法与直接调用 run 的核心区别在哪里
start() 方法的作用是异步启动线程。它首先由 JVM 创建一个新的线程对象,然后在新线程中自动调用 run() 方法。这样,主线程和子线程可以并行执行,互不阻塞。这是实现并发编程的标准方式。
public class StartDemo {
public static void main(String[] args) throws InterruptedException {
MyThread thread = new MyThread();
System.out.println("Before start: " + Thread.currentThread().getName());
thread.start(); // 启动新线程
System.out.println("After start: " + Thread.currentThread().getName());
thread.join(); // 等待子线程结束
}
}
class MyThread extends Thread {
@Override
public void run() {
try {
Thread.sleep(1000); // 模拟耗时操作
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Inside run: " + Thread.currentThread().getName());
}
}预期输出(顺序可能略有不同,但线程名不同):
Before start: main After start: main Inside run: Thread-0
这里,main 线程在调用 start() 后立即继续执行,而 run() 中的逻辑在名为 Thread-0 的新线程中执行。两者并行,体现了真正的多线程特性。
如果在一个已启动的线程上再次调用 start 会发生什么
如果在已经调用过 start() 的线程对象上再次调用 start(),JVM 会抛出 IllegalThreadStateException。这是因为每个线程对象只能被启动一次,其内部状态机不允许重复进入“运行”状态。这是为了防止资源竞争和不可预测的行为。
public class DoubleStartDemo {
public static void main(String[] args) {
MyThread thread = new MyThread();
thread.start();
try {
thread.start(); // 再次调用
} catch (IllegalThreadStateException e) {
System.out.println("Exception caught: " + e.getClass().getSimpleName());
}
}
}
class MyThread extends Thread {
@Override
public void run() {
System.out.println("Running...");
}
}预期输出:
Running... Exception caught: IllegalThreadStateException
这表明 Java 线程模型对线程生命周期有严格的管理,确保每个线程只被激活一次。开发者应避免这种错误用法,如果需要重新执行任务,应创建新的线程实例。


















