--- title: "Java 并发编程完整指南:从线程基础到 JUC 进阶" date: "2026-05-26" category: "后端开发" tags: ["Java", "并发", "JUC"] excerpt: "全面梳理 Java 并发编程知识体系,从线程基础、synchronized 原理到 JUC 并发工具类。" --- ## 一、线程基础知识 ### 1.1 线程的生命周期 Java 线程在它的生命周期中会经历六种状态: - **NEW** — 线程刚创建,尚未调用 `start()` - **RUNNABLE** — 线程在 JVM 中运行 - **BLOCKED** — 线程被阻塞,等待获取锁 - **WAITING** — 无限期等待 - **TIMED_WAITING** — 超时等待 - **TERMINATED** — 线程已执行完毕 > 重要区别:BLOCKED 是在等待进入 synchronized 块时发生的,而 WAITING 是通过 Object.wait()、Thread.join() 等方法进入的。 ### 1.2 线程的创建方式 Java 中创建线程主要有四种方式: **继承 Thread 类** ```java class MyThread extends Thread { @Override public void run() { System.out.println("线程运行中: " + Thread.currentThread().getName()); } } MyThread thread = new MyThread(); thread.start(); ``` **实现 Runnable 接口** ```java class MyRunnable implements Runnable { @Override public void run() { System.out.println("线程运行中"); } } Thread thread = new Thread(new MyRunnable()); thread.start(); ``` **Callable 与 Future** ```java class MyCallable implements Callable { @Override public String call() throws Exception { Thread.sleep(1000); return "任务完成"; } } ExecutorService executor = Executors.newSingleThreadExecutor(); Future future = executor.submit(new MyCallable()); String result = future.get(); ``` ## 二、synchronized 原理 ### 2.1 对象头与 Monitor Java 中的每个对象都与一个 Monitor 关联。`synchronized` 关键字的底层实现依赖于对象头中的 Mark Word 和 Monitor 机制。 - **Mark Word**:存储对象的 HashCode、GC 分代年龄、锁状态标志 - **Monitor**:包含 EntryList、WaitSet、Owner 三个关键部分 ```java public class Counter { private int count = 0; public synchronized void increment() { count++; } public void incrementWithBlock() { synchronized (this) { count++; } } } ``` ### 2.2 锁升级过程 JDK 1.6 之后,锁不再直接膨胀为重量级锁,而是逐步升级: | 锁状态 | 适用场景 | 实现原理 | |--------|----------|----------| | 偏向锁 | 只有一个线程访问 | Mark Word 记录线程 ID | | 轻量级锁 | 多线程交替执行 | CAS + 自旋 | | 重量级锁 | 竞争激烈 | OS Mutex Lock | ## 三、JUC 并发工具 ### 3.1 ReentrantLock 比 synchronized 更灵活的锁实现: ```java ReentrantLock lock = new ReentrantLock(true); lock.lock(); try { // 临界区代码 } finally { lock.unlock(); } ``` ### 3.2 CountDownLatch 等待其他线程完成操作: ```java CountDownLatch latch = new CountDownLatch(3); for (int i = 0; i < 3; i++) { new Thread(() -> { // 执行任务... latch.countDown(); }).start(); } latch.await(); ``` ### 3.3 Semaphore 控制同时访问资源的线程数量: ```java Semaphore semaphore = new Semaphore(5); semaphore.acquire(); try { // 最多5个线程同时执行 } finally { semaphore.release(); } ``` ## 四、线程池原理 ### 4.1 核心参数 ```java public ThreadPoolExecutor( int corePoolSize, // 核心线程数 int maximumPoolSize, // 最大线程数 long keepAliveTime, // 空闲线程存活时间 TimeUnit unit, BlockingQueue workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler ) ``` 工作流程:核心线程 → 任务队列 → 最大线程 → 拒绝策略 ### 4.2 拒绝策略 - **AbortPolicy** — 抛出异常 - **CallerRunsPolicy** — 由提交线程自己执行 - **DiscardPolicy** — 静默丢弃 - **DiscardOldestPolicy** — 丢弃最早的未处理任务 ## 五、虚拟线程 Java 21 正式引入了虚拟线程: ```java Thread vThread = Thread.ofVirtual() .name("virtual-thread-1") .start(() -> { System.out.println("虚拟线程运行中"); }); ``` > 传统"一个请求一个线程"模式在虚拟线程诞生后变得不再昂贵。对于 IO 密集型应用,虚拟线程可以显著提升吞吐量。