java Semaphore 信号量理解与示例
是什么
给定一定数量的许可证,用于调用者获取,如果许可证都被占用,那么就进入阻塞状态;
可以理解为上公共厕所,厕所只有2个坑位,目前有3个人,那么同时只能有2个人进去,第三人想要进去那么就必须等占用坑位的人完事之后才OK
目前在业务上没遇到信号量场景,能想到的就是对单体应用请求限流,下面就给出一个示例
使用信号量限流示例
import java.time.LocalDateTime;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.LockSupport;
/**
*
* 信号量实现限流示例
* @author 唐海斌
* @date 2022/8/17 13:24
*/
public class SemaphoreLimit {
/**
* 同时允许2个客户端同时访问资源
*/
static Semaphore semaphore = new Semaphore(2);
public static void limit() {
try {
//当未获取到许可会阻塞,直到有新的许可
semaphore.acquire();
System.out.println(LocalDateTime.now() + "------>>>> 获取到许可...");
//将线程阻塞10秒,模拟业务处理
LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(10));
semaphore.release();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(10);
for (int index = 0; index < 10; ++index) {
executorService.execute(SemaphoreLimit::limit);
}
}
}
原理
从源码上分析
abstract static class Sync extends AbstractQueuedSynchronizer {
//非公平信号量实现
final int nonfairTryAcquireShared(int acquires) {
for (; ; ) {
//获取可用许可数量
int available = getState();
//剩余许可数 = 可用许可数 - 请求许可数
int remaining = available - acquires;
//可用许可数小于0直接返回,在调用方死循环调用当前方法;可用许可数大于0就采用CAS比较更新剩余许可数的值
if (remaining < 0 ||
compareAndSetState(available, remaining))
return remaining;
}
}
}
总结
内部实现了AQS同步器,采用许可数递减的方式发放许可,当许可数小于1就死循环获取许可直到有空闲的许可证;所以能限制在同一时间内最多有指定数量的线程可以访问资源
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南