Java Thread线程1—线程基础
线程的创建
方式一:继承 Thread 类(不推荐,耦合度高)
public class MyThread extends Thread {
@Override
public void run() {
System.out.println("线程运行中:" + Thread.currentThread().getName());
}
public static void main(String[] args) {
MyThread t1 = new MyThread();
t1.start(); // 启动线程
}
}
缺点:Java 是单继承,继承 Thread 后不能再继承其他类,扩展性差。
方式二:实现 Runnable 接口(推荐,解耦)
public class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println("线程运行中:" + Thread.currentThread().getName());
}
public static void main(String[] args) {
Thread t1 = new Thread(new MyRunnable());
t1.start();
}
}
方式三:实现 Callable 接口(支持返回值和异常)
import java.util.concurrent.*;
public class MyCallable implements Callable<String> {
@Override
public String call() throws Exception {
return "线程返回值:" + Thread.currentThread().getName();
}
public static void main(String[] args) throws Exception {
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<String> future = executor.submit(new MyCallable());
System.out.println(future.get()); // 获取返回值
executor.shutdown();
}
}
总结对比表
| 方式 | 是否返回值 | 是否抛异常 | 是否可继承其他类 | 使用场景 |
|---|---|---|---|---|
| Thread | ❌ | ❌ | ❌ | 简单演示 |
| Runnable | ❌ | ❌ | ✅ | 大多数并发任务 |
| Callable | ✅ | ✅ | ✅ | 需要返回结果的任务 |
现代推荐:使用线程池(ExecutorService)
ExecutorService pool = Executors.newFixedThreadPool(3);
pool.execute(() -> System.out.println("线程池执行任务"));
pool.shutdown();
日常开发中,优先使用 Runnable + 线程池(ExecutorService),避免直接操作 Thread。
线程的生命周期
在 Java 中,线程(Thread)的生命周期由 JVM 和操作系统共同管理,其状态转换遵循 Thread.State 枚举定义的 6 种状态。下面用“时间轴+状态图+代码验证”的方式,一次性讲透。
官方 6 状态图(JDK 源码:java.lang.Thread.State)
| 状态名 | 中文含义 | 触发条件/备注 |
| NEW | 新建 | 刚 new Thread(),还未 start() |
| RUNNABLE | 可运行 | start() 后,可能正在 CPU 运行,也可能在等待调度 |
| BLOCKED | 阻塞 | 等待 monitor lock(进入 synchronized 块/方法) |
| WAITING | 无限等待 | 主动调用 wait()、join()、LockSupport.park() 等,无超时 |
| TIMED_WAITING | 限时等待 | 调用 sleep(time)、wait(time)、join(time)、parkNanos 等,有超时 |
| TERMINATED | 终止 | run() 执行完毕或异常退出 |
生命周期时间轴(一张图记住)

代码实时查看状态
public class LifeCycleDemo {
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread(() -> {
synchronized (LifeCycleDemo.class) {
try {
LifeCycleDemo.class.wait(); // WAITING
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
});
System.out.println("1. NEW: " + t.getState()); // NEW
t.start();
Thread.sleep(50);
System.out.println("2. RUNNABLE: " + t.getState()); // RUNNABLE
synchronized (LifeCycleDemo.class) {
Thread.sleep(50);
System.out.println("3. BLOCKED: 主线程拿到锁,子线程阻塞 " + t.getState()); // BLOCKED
LifeCycleDemo.class.notify();
}
Thread.sleep(50);
System.out.println("4. TERMINATED: " + t.getState()); // TERMINATED
}
}
易混淆点速记
| 场景 | 所属状态 | 原因说明 |
| Thread.sleep(1000) | TIMED_WAITING | 不释放锁,限时休眠 |
| obj.wait() | WAITING | 释放锁,需 notify() |
| synchronized 竞争锁 | BLOCKED | 未拿到 monitor |
| lock.lock() (ReentrantLock) | 不是 BLOCKED | 在 JDK 层面是 WAITING/TIMED_WAITING,JVM 不感知 |
| yield() | 仍是 RUNNABLE | 只是提示调度器让出 CPU,状态不变 |
| join() | 当前线程进入 WAITING/TIMED_WAITING | 等待目标线程结束 |
Thread.State 枚举定义的 6 种状态中为啥没Running
在 Thread.State 枚举里确实只有 RUNNABLE 而没有 RUNNING,这并不是遗漏,而是 有意为之
Java 把“正在 CPU 上跑”和“可跑但还没分到 CPU”这两件事合并成了同一个状态:RUNNABLE。
OS vs JVM 视角
| 视角 | 状态个数 | 状态名示例 | 备注 |
| OS | 3+ | RUNNING, READY, BLOCKED | 内核调度器可见 |
| JVM | 6 | RUNNABLE, BLOCKED, WAITING… | 跨平台抽象层 |
-
RUNNING 是 操作系统内核 里的概念,表示 当前占用 CPU。
-
JVM 为了跨平台,把“READY + RUNNING”统一成 RUNNABLE,不暴露底层调度细节。
这样无论 Windows、Linux、macOS 调度策略如何,Java 程序看到的状态都一样。
更多推荐

所有评论(0)