正确启动方式是调用start();start()会创建新线程并由jvm自动调用run(),而直接调用run()仅在当前线程同步执行,不启新线程。

Java中Thread类的run()方法默认不执行任何操作,它只是一个空方法;真正起作用的是你重写它后定义的具体任务逻辑。
run()方法的默认行为:空实现
Thread类中的run()方法在源码中定义如下:
public void run() {
if (target != null) {
target.run();
}
}
其中target是Runnable对象(通过构造函数传入)。若你用的是无参构造创建Thread,且未传入Runnable,那么target为null,整个run()方法就什么也不做。
这意味着:直接调用new Thread().run()不会开启新线程,也不会报错,只是执行一个空方法——这和调用普通方法完全一样。
重写run()的两种常见方式
要让线程真正执行自定义逻辑,必须让run()方法“有事可做”。主要有以下两种做法:
- 继承Thread类并重写run():适合任务逻辑与线程强绑定、复用性要求不高的场景。例如:
class MyThread extends Thread {
public void run() {
System.out.println("线程正在运行:" + Thread.currentThread().getName());
}
}
new MyThread().start(); // 注意:必须调用start(),不是run()
- 实现Runnable接口,传给Thread构造器:更推荐,符合面向接口编程原则,避免单继承限制,也利于任务与线程解耦。例如:
Runnable task = () -> System.out.println("Lambda方式执行任务");
new Thread(task).start();
start()和run()的核心区别
这是初学者最容易混淆的关键点:
-
start():通知JVM开启新线程,并由JVM自动调用该线程的run()方法——这才是真正的多线程执行。 -
run():只是一个普通实例方法。直接调用它,代码仍在当前线程中同步执行,不会启动新线程。
错误示范:
Thread t = new MyThread();
t.run(); // ❌ 串行执行,无并发效果
t.start(); // ✅ 正确:启动新线程并执行run()
为什么建议优先使用Runnable而非继承Thread
除了设计灵活性外,还有几个实际好处:
- Java不支持多继承,但一个类可以实现多个接口——如果你的业务类 already 继承了其他父类,就无法再继承
Thread,但实现Runnable毫无压力。 - 同一个
Runnable实例可被多个Thread复用,便于共享任务状态或统一调度。 - 现代并发编程(如
ExecutorService)只接受Runnable或Callable,不接受Thread子类。
所以,除非有特殊需求(比如需要在子类中封装线程生命周期管理逻辑),否则应优先选择Runnable方式。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











