Semaphore 是 Java 并发工具类,基于 许可证(Permits)机制 控制同时访问共享资源的线程数量。常用于限流、资源池管理、生产者-消费者模型等场景,支持公平与非公平模式。
一、核心功能
- 流量控制:限制同时访问资源的线程数量(如数据库连接池)。
- 许可证管理:线程通过
acquire()获取许可证,release()释放许可证。 - 模式可选:支持公平模式(按等待顺序分配)与非公平模式(允许插队)。
二、核心方法
| 方法 | 说明 |
|---|---|
Semaphore(int permits) | 构造方法,指定许可证数量(默认非公平模式) |
Semaphore(int permits, boolean fair) | 指定许可证数量和公平性 |
void acquire() | 获取一个许可证(阻塞直到获取或中断) |
boolean tryAcquire() | 尝试获取许可证(非阻塞,立即返回结果) |
boolean tryAcquire(long timeout, TimeUnit unit) | 带超时的尝试获取 |
void release() | 释放一个许可证(需与 acquire() 配对使用) |
int availablePermits() | 返回当前可用许可证数量 |
void reducePermits(int reduction) | 减少许可证数量(Java 17+) |
三、典型使用场景
- 资源池管理 例如:限制数据库连接池的最大并发连接数。
- 接口限流 例如:控制每秒处理请求的线程数量。
- 生产者-消费者模型 通过信号量协调生产者和消费者的速率。
四、代码示例(停车场模型)
public class SemaphoreDemo {
public static void main(String[] args) {
int parkingSpots = 3; // 3个车位
Semaphore semaphore = new Semaphore(parkingSpots, true); // 公平模式
for (int i = 1; i <= 5; i++) { // 5辆车竞争车位
new Thread(() -> {
try {
semaphore.acquire(); // 获取车位
System.out.println(Thread.currentThread().getName() + " 停车成功");
Thread.sleep(2000); // 模拟停车时间
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
semaphore.release(); // 释放车位
System.out.println(Thread.currentThread().getName() + " 离开车位");
}
}, "车辆-" + i).start();
}
}
}
输出结果:
车辆-1 停车成功
车辆-2 停车成功
车辆-3 停车成功
车辆-1 离开车位
车辆-4 停车成功
车辆-2 离开车位
车辆-5 停车成功
...(后续交替执行)
五、注意事项
- 许可证必须释放 确保在
finally块中调用release(),避免线程阻塞导致资源泄漏。 - 避免超额释放 释放次数不应超过获取次数(否则许可证数量会异常增加)。
- 公平模式开销 公平模式基于队列维护顺序,性能略低于非公平模式。
- 动态调整许可证 Java 17+ 支持
increasePermits()和reducePermits(),但需注意线程安全。
六、对比其他同步工具
| 特性 | Semaphore | ReentrantLock | CountDownLatch |
|---|---|---|---|
| 核心能力 | 控制并发数量 | 互斥锁 | 等待事件完成 |
| 可重用性 | 支持 | 支持(需解锁) | 一次性 |
| 公平性 | 可选 | 可选 | 无 |
七、高级用法
1. 多资源单位申请(批量获取许可证)
semaphore.acquire(2); // 一次获取2个许可证(需足够可用)
semaphore.release(2); // 释放2个许可证
2. 非阻塞尝试(快速失败)
if (semaphore.tryAcquire()) { // 立即返回是否成功
try { /* 使用资源 */ }
finally { semaphore.release(); }
} else {
System.out.println("资源不足,拒绝请求");
}
3. 动态扩容(Java 17+)
semaphore.reducePermits(2); // 减少2个许可证(如资源故障)
semaphore.increasePermits(2); // 增加2个许可证(如资源恢复)
总结: Semaphore 是灵活的资源并发控制器,通过许可证机制实现精准的流量限制。适用于资源池化、接口限流等场景,需注意许可证的获取与释放必须严格匹配,避免死锁和资源泄漏。