semaphore的核心作用是并发数量控制——确保同一时刻最多n个线程进入临界区或使用资源,适用于数据库连接数限制、文件i/o并发控制、api调用频控等场景,并需注意公平性、中断处理与异常安全。

Semaphore 的核心作用就是对并发任务做“数量闸门”控制——它不关心谁在执行,只确保同一时刻最多有 N 个线程能进入受保护的代码段或使用某类资源。
控制数据库连接数
数据库连接池通常有硬性上限(比如 10 个活跃连接),超出就会抛出异常或拒绝服务。用 Semaphore 可以提前拦截:
- 初始化
Semaphore semaphore = new Semaphore(10),代表最多 10 个许可 - 每个任务执行前调用
semaphore.acquire(),拿不到许可就排队等待 - 操作完成后必须在
finally块中调用semaphore.release(),避免许可泄漏 - 即使底层连接池未满,Semaphore 也能防止瞬时高并发压垮连接获取逻辑
限制文件读写并发度
频繁读写磁盘可能引发 I/O 瓶颈或文件锁冲突,尤其在多线程处理大量小文件时:
- 设
Semaphore fileLock = new Semaphore(4),把并发数压到系统可承受的 I/O 并发水平 - 每次打开/写入文件前先
acquire(),写完立即release() - 相比 synchronized 或 ReentrantLock,Semaphore 更适合“N选一”而非“独占”,语义更清晰
- 可配合 tryAcquire(long, TimeUnit) 设置超时,避免某个卡死的文件操作拖住整个队列
API 调用频控与下游保护
调用外部服务(如短信网关、支付接口)时,既要遵守对方限流规则,也要防止自身线程耗尽:
- 按服务商要求设置许可数,例如每秒最多 5 次调用 →
new Semaphore(5) - 每次发起 HTTP 请求前获取许可,响应返回后释放
- 结合 ScheduledExecutorService,可实现“每秒重置许可”的令牌桶效果(需额外计时逻辑)
- 比单纯 sleep 或 Thread.sleep 更可靠:阻塞是协作式,不浪费 CPU,且能响应中断
公平性与异常安全要点
默认非公平模式效率高但顺序不确定;若需严格 FIFO 排队,构造时传 true:
-
new Semaphore(3, true)启用公平策略,先到先得 -
acquire()可能被中断,务必捕获InterruptedException并恢复中断状态 - 永远把
release()放在finally中——哪怕业务逻辑抛异常,许可也必须归还 - 避免在 acquire 后、release 前长时间阻塞(如复杂计算),否则会人为拉长许可占用周期











