主题切换
控制并发访问线程数量
一、核心工具:Semaphore(信号量)
基础介绍
- 归属:JUC并发工具类,底层基于AQS同步队列实现;
- 核心作用:限制同一时间访问指定资源/方法的最大并发线程数,常用于接口限流、有限资源调度;
- 通俗类比:停车场固定车位,初始化容量=车位总数,只有拿到车位许可才能进入,离开后释放车位。
二、核心API与使用步骤
三大核心方法
Semaphore(int permits)构造方法 传入许可数量,代表同一时间最多允许permits个线程并发执行。acquire()获取许可 信号量许可数-1;无可用许可时线程阻塞,直到其他线程释放许可。release()释放许可 信号量许可数+1,一般放在finally块,保证无论正常/异常执行都会归还许可。
标准使用流程
- 全局初始化Semaphore,指定最大并发许可;
- 进入目标方法前调用
acquire()抢占许可; - 执行业务逻辑;
finally中调用release()释放许可。
完整示例代码
java
// 最多允许3个线程同时执行该方法
Semaphore semaphore = new Semaphore(3);
public void limitMethod() throws InterruptedException {
// 获取许可,无许可则阻塞
semaphore.acquire();
try {
System.out.println("线程执行业务逻辑");
Thread.sleep(1000);
} finally {
// 必须释放,防止死锁
semaphore.release();
}
}三、业务使用场景
- 第三方接口限流:调用付费/有限流限制的外部API,控制并发避免被封禁;
- 数据库大批量操作:限制同时操作DB的线程,防止打满连接池;
- 文件/硬件资源调度:有限IO资源,控制并发读写数量;
- 接口并发限流:单接口限制最大同时访问线程,保护服务。
四、总结
- Semaphore底层依靠AQS实现,用于精准控制方法/资源最大并发线程数;
- 三步核心操作:初始化许可容量 → acquire()抢占许可 → finally中release()释放;
- 适用场景:资源有限、需要限流的并发场景,区别于锁(锁同一时间仅1线程,信号量可允许多个并发)。
五、面试简答
问:如何限制一个方法同时最多N个线程并发访问? 答:使用JUC的Semaphore信号量,底层基于AQS。构造方法传入N代表最大并发许可;方法执行前调用acquire()获取许可,无许可线程阻塞;业务代码放入try块,finally执行release()归还许可,以此控制同一时间最多N个线程进入方法,常用于接口限流、第三方调用控并发。