文章目录
- 一、什么是信号量
- 二、信号量有什么用
- 三、信号量怎么用
- 四、有哪些核心方法
- 五、参考博文
一、什么是信号量
Semaphore存在于java.util.concurrent(java并发)包下,,是一个计数信号量,维护了一个许可的集,若有必要,会在获取许可前阻塞每一个线程。
二、信号量有什么用
假想在服务器上运行着若干线程,这些线程需要连接到同一数据库,但任一时刻只能获得一定数目的数据库连接。要怎样才能够有效地将这些固定数目的数据库连接分配给若干线程?
方案一:给方法加锁,那样从始至终只会有一个数据库连接可用,此方案不可用;
方案二:使用Semaphore,通常用于限制并发访问某些资源(物理或逻辑的)的线程数目。此方案可行
三、信号量怎么用
构造函数
Semaphore(int permits,boolean fair)
permits:许可数
fair:如果信号量想在征用时按照FIFO授予许可,则为true,否则为false,默认为false
Semaphore(int permits)
生活案例:排队上厕所,排队用餐,排队去银行柜台办理业务等等
@Test
void testSemaphore() {
// 建立缓存线程池
ExecutorService executorService = Executors.newCachedThreadPool();
// 定义信号量
int permitsNum = 5;
Semaphore semaphore = new Semaphore(permitsNum);
// 启动20个线程
for (int i = 0; i < 20; i++) {
Runnable runnable = new Runnable() {
@Override
public void run() {
if(semaphore.availablePermits() > 0 ){
System.out.println("Thread " + Thread.currentThread().getName() + " 准备获取许可 " + "当前系统的并发数是:" + (permitsNum - semaphore.availablePermits()));
}else{
System.out.println("Thread " + Thread.currentThread().getName() + " 没有许可,排队等待 " + "当前系统的并发数是:" + (permitsNum - semaphore.availablePermits()));
}
try {
semaphore.acquire();
System.out.println("Thread " + Thread.currentThread().getName() + " 已经获取到许可 " + "当前系统的并发数是:" + (permitsNum - semaphore.availablePermits()));
Thread.sleep((long) (Math.random() * 10000));
System.out.println("Thread " + Thread.currentThread().getName() + " 任务执行完毕,准备归还许可");
} catch (Exception e) {
System.out.println("exception " + e.getMessage());
} finally {
semaphore.release();
System.out.println("Thread " + Thread.currentThread().getName() + " 已经归还许可,当前系统的并发数是:" + (permitsNum - semaphore.availablePermits()));
}
}
};
// 执行线程
executorService.execute(runnable);
}
// 关闭线程池
executorService.shutdown();
// Uninterruptibly 不间断地
System.out.println("Thread " + Thread.currentThread().getName() + " 将线程阻塞");
semaphore.acquireUninterruptibly(2);
System.out.println("Thread " + Thread.currentThread().getName() + " 归还许可");
semaphore.release(2);
}
四、有哪些核心方法
1、void acquire()
Acquires a permit from this semaphore, blocking until one is available, or the thread is interrupted
从这个信号量获取许可证,阻塞直到有一个可用或者线程被中断
从信号量获取一个许可,在提供一个许可前当前线程会阻塞。如果成功获取了许可并立即返回,将信号量中的有用许可减一;如果获取失败,则抛出中断异常,线程被中断
2、void acquireUninterruptibly()
与acquire()方法相同,但是如果当前线程在等待许可时被中断,那么他会继续等待
3、boolean tryAcquire()
Acquires a permit from this semaphore, only if one is available at the time of invocation
如果只有一个信号量可用,则从该信号量获取许可证调用时间。
仅仅调用此信号量存在一个可用的许可,如果存在返回true ,不存在则返回false 并立即返回 。
4、boolean tryAcquire(0,TimeUnit.SECONDS)
在单位等待时间内获取许可,这样希望是遵守公平的设置,如果已经超出等待时间会立即返回。
5、void release()
释放一个许可,将其归还给指定的信号量