Runnable接口不创建线程,仅定义任务;真正创建并启动线程的是Thread类或线程池;直接调用run()无并发效果,须用start();匿名类、Lambda、独立类三种实现方式各适配不同场景。
这是最常被误解的一点:Runnable 是一个函数式接口,只规定了 run() 方法签名,它不启动线程、不管理生命周期、也不持有线程资源。真正创建并启动线程的是 Thread 类或线程池。
常见错误现象:直接调用 myRunnable.run() —— 这只是普通方法调用,仍在当前线程执行,**完全不并发**。
Runnable 实例传给 Thread 构造器,再调用 thread.start()
start() 才会触发 JVM 创建新线程并回调 run()
start() 会抛出 IllegalThreadStateException
实际开发中,Runnable 的实现方式影响可读性、复用性和维护成本。
匿名内 
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("Hello from thread: " + Thread.currentThread().getName());
}
}).start();
Lambda(Java 8+,推荐用于无状态逻辑):
new Thread(() -> {
System.out.println("Hello from lambda thread");
}).start();
独立类实现(适合需复用、含状态或需测试的场景):
public class CounterTask implements Runnable {
private final int count;
public CounterTask(int count) { this.count = count; }
@Override
public void run() {
for (int i = 0; i < count; i++) {
System.out.println(Thread.currentThread().getName() + ": " + i);
}
}
}
// 使用
new Thread(new CounterTask(5)).start();
MyApp$1),不利于排查线程 dump这不是风格偏好,而是 Java 语言机制和工程实践的硬约束。
Frame、Activity),就无法再 extends Thread
Runnable 更符合“单一职责”:任务逻辑(what)与执行机制(how)分离ExecutorService)只接受 Runnable 或 Callable,不接受 Thread 子类Runnable + 线程池才是生产环境标准做法很多人以为只要用了 Runnable 就“多线程了”,却没意识到共享数据的风险。
Thread 实例共用同一个 Runnable 对象(尤其用 Lambda 捕获外部变量时),其字段可能被并发修改Runnable,若它们操作静态变量、单例对象或传入的共享集合,仍需同步System.out.println() 虽然线程安全,但输出可能交错(如 “A1B2C3”),不代表业务逻辑安全run() 中吞掉异常:未捕获的 RuntimeException 会导致线程静默终止,且不会传播到主线程线程真正的复杂点不在怎么启动,而在共享状态的可见性、原子性和有序性——这些靠 Runnable 接口本身解决不了,得靠 synchronized、volatile、java.util.concurrent 工具类来兜底。