
Semaphore介绍
Semaphore,俗称信号量,它是操作系统中PV操作的原语在java的实现,它也是基于
AbstractQueuedSynchronizer实现的。
Semaphore的功能非常强大,大小为1的信号量就类似于互斥锁,通过同时只能有一个线程获
取信号量实现。大小为n(n>0)的信号量可以实现限流的功能,它可以实现只能有n个线程同
时获取信号量。

PV操作是操作系统一种实现进程互斥与同步的有效方法。
PV操作与信号量(S)的处理相关,P表示通
过的意思,V表示释放的意思。用PV操作来管理共享资源时,首先要确保PV操作自身执行的正确性。
P操作的主要动作是:
①S减1;
②若S减1后仍大于或等于0,则进程继续执行;
③若S减1后小于0,则该进程被阻塞后放入等待该信号量的等待队列中,然后转进程调度。
V操作的主要动作是:
①S加1;
②若相加后结果大于0,则进程继续执行;
③若相加后结果小于或等于0,则从该信号的等待队列中释放一个等待进程,然后再返回原进程继续执
行或转进程调度。
Semaphore 常用方法
构造器

permits 表示许可证的数量(资源数)
fair 表示公平性,如果这个设为 true 的话,下次执行的线程会是等待最
久的线程
常用方法
1
public void
acquire
()
throws InterruptedException
2
public
boolean
tryAcquire
()
3
public void
release
()
4
public
int
availablePermits
()
5
public
final int
getQueueLength
()
6
public
final boolean
hasQueuedThreads
()
7
protected void
reducePermits
(
int reduction
)
8
protected
Collection
<
Thread
>
getQueuedThreads
()
acquire() 表示阻塞并获取许可 可理解为lock 加锁
tryAcquire() 方法在没有许可的情况下会立即返回 false,要获取许可的线程不会阻
塞
release() 表示释放许可 可理解为释放锁
int availablePermits():返回此信号量中当前可用的许可证数。
int getQueueLength():返回正在等待获取许可证的线程数。
boolean hasQueuedThreads():是否有线程正在等待获取许可证。
void reducePermit(int reduction):减少 reduction 个许可证
Collection getQueuedThreads():返回所有等待获取许可证的线程集合
应用场景
可以用于做流量控制,特别是公用资源有限的应用场景
限流
1
public class
SemaphoneTest2
{
2
3
/**
4
*
实现一个同时只能处理
5
个请求的限流器
5
*/
6
private static
Semaphore semaphore
=
new
Semaphore
(
5
);
7
8
/**
9
*
定义一个线程池
10
*/
11
private static
ThreadPoolExecutor executor
=
new
ThreadPoolExecutor
(
10
,
50
,
60
,
TimeUnit
.
SECONDS
,
new
LinkedBlockingDeque
<>
(
200
));
12
13
/**
14
*
模拟执行方法
15
*/
16
public static void
exec
() {
17
try
{
18
semaphore
.
acquire
(
1
);
19
//
模拟真实方法执行
20
System
.
out
.
println
(
"
执行
exec
方法
"
);
21
Thread
.
sleep
(
2000
);
22
}
catch
(
Exception e
) {
23
e
.
printStackTrace
();
24
}
finally
{
25
semaphore
.
release
(
1
);
26
}
27
}
28
29
public static void
main
(
String
[]
args
)
throws InterruptedException
{
30
{
31
for
(; ; ) {
32
Thread
.
sleep
(
100
);
33
//
模拟请求以
10
个
/s
的速度
34
executor
.
execute
(()
‐>
exec
());
35
}
36
}
37
}
38
}