线程的创建与运行
掌握 Thread、Runnable、Callable、线程状态与生命周期
线程的创建与运行
你的程序默认只有一个"主线程"在跑。多线程就是同时开启多条执行路径,比如一边下载文件一边更新进度条。但多线程也带来竞态条件、死锁等复杂问题——所以理解基础原理至关重要。
学完本章你将: 掌握三种创建线程方式、线程状态、常用控制方法。
创建线程的三种方式
Java 中启动一个新线程,本质上是把一段代码(run() 方法)交给 JVM 的线程调度器去执行。关键在于:调用 start() 才会创建新线程,直接调用 run() 只是普通方法调用。
java
// 方式 1:继承 Thread(简单但不灵活——Java 单继承,不能再继承其他类)
class MyThread extends Thread {
@Override
public void run() {
System.out.println(getName() + " 执行中"); // getName() 获取线程名
}
}
new MyThread().start(); // ✅ 新线程执行 run()
// new MyThread().run(); // ❌ 当前线程执行,不是多线程!
java
// 方式 2:实现 Runnable(推荐——任务和线程分离,还能继承其他类)
class MyTask implements Runnable {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " 执行");
}
}
Thread t = new Thread(new MyTask(), "Worker-1"); // 起个名字方便调试
t.start();
java
// 方式 3:Callable + Future(有返回值,能抛异常)
Callable<Integer> task = () -> {
Thread.sleep(1000); // 模拟耗时操作
return 42; // 返回计算结果
};
FutureTask<Integer> future = new FutureTask<>(task);
new Thread(future).start();
System.out.println("结果:" + future.get()); // get() 阻塞等待,拿到 42 后才继续
| 方式 | 有返回值 | 能抛异常 | 推荐度 |
|---|---|---|---|
| Thread | ❌ | ❌ | 简单场景 |
| Runnable | ❌ | ❌ | ⭐ 日常首选 |
| Callable | ✅ | ✅ | 需要结果时用 |
Lambda 简化写法
java
// Runnable — 一行搞定
new Thread(() -> System.out.println("Hello!")).start();
// Callable + 线程池(不直接 new Thread)
ExecutorService pool = Executors.newSingleThreadExecutor();
Future<String> result = pool.submit(() -> "任务完成");
System.out.println(result.get());
pool.shutdown(); // 别忘了关闭线程池
线程状态 —— 生命周期
┌─ NEW(刚创建,还没 start)
↓
RUNNABLE(运行中 / 等待 CPU)
↙ ↓ ↘
BLOCKED WAITING TIMED_WAITING(各种等待状态)
↘ ↓ ↙
TERMINATED(执行完毕)
java
Thread t = new Thread(() -> {}); // NEW
t.start(); // RUNNABLE
t.join(); // 等 t 结束
System.out.println(t.getState()); // TERMINATED
💡 RUNNABLE 不等于"正在运行"。 它只是"可运行"——可能在跑,也可能在排队等 CPU。具体由操作系统调度,你控制不了。
常用控制方法
java
Thread.sleep(1000); // 让当前线程暂停 1 秒(不释放锁!)
t.join(); // 等待线程 t 执行完毕再继续
t.setPriority(Thread.MAX_PRIORITY); // 设优先级(1~10,只是建议,不保证)
t.setDaemon(true); // 设为守护线程:主线程结束,守护线程自动终止
Thread.yield(); // 主动让出 CPU(只是建议,JVM 可能忽略)
⚠️ 守护线程注意: GC 就是典型的守护线程。如果你把重要业务线程设为守护线程,一旦主线程结束它就被强制终止——可能数据写到一半就没了。