Semaphore的使用

概述

Semaphore 是一个计数信号量,常用于限制可以访问某些资源(物理或逻辑的)线程数目。

方法

构造方法

Semaphore(int)、Semaphore(int,boolean)

int 表示该信号量拥有的许可数量

boolean 表示获取许可的时候是否是公平的。(公平指的是先来的先执行)

获取许可

acquire()、acquire(int)、tryAcquire()

int 参数表示一次性要获取几个许可,默认为 1 个,acquire 方法在没有许可的情况下,要获取许可的线程会阻塞。

tryAcquire()方法在没有许可的情况下会立即返回 false,要获取许可的线程不会阻塞。

释放许可

release()、release(int)

int 参数表示一次性要释放几个许可,默认为 1 个,

注意:一个线程调用 release()之前并不要求一定要调用了 acquire 因此如果释放的比获取的信号量还多,例如获取了 2 个,释放了 5 次,那么当前信号量就动态的增加为 5 了(实现动态增加)

当前可用的许可数

int availablePermits()

使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
package org.example.concurrent;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;

/**
* 常用于限流的应用场景
* @author Catch
* @since 2021/8/23 00:47
*/
public class SemaphoreCase {

// 线程池
private static final ExecutorService executorService = Executors.newCachedThreadPool();

// 只允许 2 个线程同时访问
private static final Semaphore semaphore = new Semaphore(2);

// 模拟20个客户端访问
public void doSomeThing(String threadName){
Runnable run = () -> {
try {
System.out.println( threadName + "启动");
// 获取许可
semaphore.acquire();
System.out.println(threadName + "执行, 剩余许可数: "+semaphore.availablePermits()+">>>>>>>");
//模拟实际业务逻辑
Thread.sleep((long) (Math.random() * 10000));
// 访问完后,释放
semaphore.release();
System.out.println(threadName + "释放, 剩余许可数: "+semaphore.availablePermits()+"<<<<<<<");
} catch (InterruptedException ignored) {
}
};
executorService.execute(run);
}

public static void main(String[] args) {
SemaphoreCase semaphoreCase=new SemaphoreCase();
for (int i = 0; i < 10; i++) {
semaphoreCase.doSomeThing("线程"+i);
}
}
}