【javaEE】 Semaphore信号量
前言:本文将简单介绍一下Semaphore的基本概念已经如何通过Semaphore实现资源限流的操作
一,什么是Semaphore?
举个通俗点的栗子,Semaphore就好比一个公共停车场,停车场的最大车位也就是资源的限制。
Semaphore的核心作用就是实现资源限流
基本原理
Semaphore可以实现对公共资源的使用限制,既然是使用资源,那自然就有获取资源以及释放资源操作。就好比内存的申请与释放,加锁与解锁一致。不过Semaphore获取资源需要通过两个关键的方法来实现:
Semaphore维护了一些固定的资源(就好比停车常固定车位)
- 获取资源:通过
acquire()来获取,此时会分为两种情况。- 1)能拿到,那就进去停车,畅通无阻
- 2)拿不到,没车位了,那就只能阻塞等待,直到有人把车位让出来
- 释放资源:通过
release()完成释放,就好比让出车位,此时就会唤醒外面由于没车位停车而等待的车辆(或者说是线程)
Semaphore的主要使用其实还是在多线程中,如果把车辆比作线程,那就可以限制线程之间的最大开销量,避免资源泄露的情况发送。
Semaphore和锁的区别
如果把普通的排他锁(比如 synchronized 或 ReentrantLock)比作“单人更衣室”,一次只能进一个人;那么 Semaphore 就是一个“允许多人同时使用的公共资源”,
二,常用方法
-
new Semaphore(int permits):构造方法,设定初始的可用许可数量。 -
new Semaphore(int permits, boolean fair):第二个参数可以指定是否为“公平模式”。公平模式下,排队等待的线程会严格按照“先来后到”的顺序获取许可;非公平模式下(默认),线程可以尝试“插队”,这种模式虽然不讲武德,但系统的整体吞吐量会更高。 -
acquire():获取一个许可。拿不到就死等,会响应线程中断机制。 -
tryAcquire():尝试获取许可,拿到返回true,拿不到立刻返回false,不会让线程干等。 -
release():释放一个许可。注意:在实际开发中,这个方法一定要放在finally代码块中,确保即使业务代码抛出异常,许可也能被正确归还。
三,代码案例
假设后端服务有一个非常消耗资源的接口,为了防止服务器被压垮,我们需要限制最多只能有 3 个线程同时处理请求:
public class SemaphoreDemo {
public static void main(String[] args) {
// 创建一个具有 3 个许可的信号量(停车场只有 3 个车位)
Semaphore semaphore = new Semaphore(3);
// 模拟 6 个用户的并发请求
ExecutorService threadPool = Executors.newFixedThreadPool(6);
for (int i = 1; i <= 6; i++) {
int threadId = i;
threadPool.execute(() -> {
try {
// 1. 尝试进场,获取许可
semaphore.acquire();
System.out.println("线程 " + threadId + " 拿到许可,开始处理业务...");
// 模拟业务处理耗时 2 秒
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
// 2. 业务处理完毕,释放许可
System.out.println("线程 " + threadId + " 执行完毕,释放许可。");
semaphore.release();
}
});
}
threadPool.shutdown();
}
}
运行显示:
以上就是有关Semaphore的简单认识,并不是很难,如有纰漏还请指出~~
更多推荐



所有评论(0)