AQS同步工具类

1. CountDownLatch 计数器

作用

让一个线程等待其他 N 个线程全部执行完,再继续运行。

一次性门栓,用完就废,不能重置。

核心原理

  • 基于 AQS 共享模式
  • 初始化传入 count
  • 每次 countDown() → count -1
  • await() 会阻塞,直到 count = 0

典型场景

  • 主线程等待多个子线程初始化完成
  • 分布式接口:等待多个下游调用全部返回

代码示例

1
2
3
4
5
6
7
8
9
10
// 主线程等待 3 个线程执行完
CountDownLatch latch = new CountDownLatch(3);

// 子线程执行完 countDown-1
new Thread(() -> {
latch.countDown();
}).start();

// 主线程阻塞等待
latch.await();

2. CyclicBarrier 循环屏障

作用

一组线程互相等待,所有人都到齐了,才能一起继续执行。

可以循环使用!

核心原理

  • 不是 AQS,是基于 ReentrantLock + Condition 实现
  • 所有线程调用 await() 后阻塞
  • 直到所有线程都到达屏障,才一起放行
  • 放行后可以重置继续用

典型场景

  • 多线程分批计算
  • 游戏:所有玩家加载完毕才开始
  • 批量任务:所有人准备好再一起执行

代码示例

1
2
3
4
5
6
7
// 4 个线程互相等待
CyclicBarrier barrier = new CyclicBarrier(4);

// 每个线程到达后阻塞
new Thread(() -> {
barrier.await(); // 等待所有人
}).start();

3. Semaphore 信号量限流

作用

控制同时执行的线程数量 → 限流。

比如:最多 10 个线程同时访问数据库。

核心原理

  • 基于 AQS 共享模式
  • 初始化许可数 permits
  • acquire() 获取许可(阻塞)
  • release() 释放许可
  • 可用许可 > 0 才能执行

典型场景

  • 接口限流
  • 连接池限流
  • 共享资源(DB / 文件)并发控制

代码示例

1
2
3
4
5
6
7
8
9
// 最多 5 个线程同时执行
Semaphore semaphore = new Semaphore(5);

semaphore.acquire(); // 获取许可
try {
// 执行业务
} finally {
semaphore.release(); // 释放
}

4. Exchanger 数据交换

作用

两个线程之间交换数据。

必须等到两个线程都到达,才互相交换对象。

核心原理

  • 线程 1 给线程 2 数据
  • 线程 2 给线程 1 数据
  • 一对一交换,缺一不可

典型场景

  • 管道交换
  • 生产者消费者直接交换数据
  • 线程间数据传输

代码示例

1
2
3
4
5
6
7
8
9
10
11
Exchanger<String> exchanger = new Exchanger<>();

// 线程A
String A = exchanger.exchange("来自A");

// 线程B
String B = exchanger.exchange("来自B");

// 结果:
// A 拿到 B 的数据
// B 拿到 A 的数据

对比

工具 作用 特点 能不能复用
CountDownLatch 一个线程等其他线程 计数器减到 0 放行 不能复用
CyclicBarrier 一组线程互相等 全部到齐一起走 可循环使用
Semaphore 控制并发线程数 限流、许可机制 永久可用
Exchanger 两个线程交换数据 一对一交换 永久可用

一句话记忆口诀

  • CountDownLatch:我等你们,你们干完我再干(一次性)
  • CyclicBarrier:我们互相等,所有人到齐一起干(可循环)
  • Semaphore:最多几个人同时干(限流)
  • Exchanger:咱俩换东西(一对一交换)

AQS同步工具类
http://hanqichuan.com/2026/04/16/java并发/AQS同步工具类/
作者
韩启川
发布于
2026年4月16日
许可协议