基本概念

Semaphore是一个计数信号量,它可以用来控制对某一资源的访问数量。在Java中,Semaphore位于java.util.concurrent包中

Semaphore的用途

流量控制:Semaphore可以用来控制同时访问特定资源的线程数量,例如数据库连接、文件句柄等
分配资源:Semaphore可以用来分配有限数量的资源,例如线程池、线程队列等

Semaphore的使用技巧

  1. 创建Semaphore
1
Semaphore semaphore = new Semaphore(5);  
  1. 获取信号量
1
semaphore.acquire();  

请求一个信号量,这时候的信号量个数-1(是尝试获取,如果是>0就减去, 否则阻塞等待信号量>0)

  1. 释放信号量
1
semaphore.release();  

信号量+1

  1. 使用tryAcquire方法
1
boolean acquired = semaphore.tryAcquire();  

上述代码尝试获取信号量,如果成功则返回true,否则返回false

  1. 使用tryAcquire(long timeout, TimeUnit unit)方法
1
boolean acquired = semaphore.tryAcquire(1000, TimeUnit.MILLISECONDS);  

上述代码尝试获取信号量,如果成功则返回true,否则在指定的时间内返回false

力扣1116 打印零与奇偶数

https://leetcode.cn/problems/print-zero-even-odd/description/

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
class ZeroEvenOdd {
private int n;

public ZeroEvenOdd(int n) {
this.n = n;
}

// printNumber.accept(x) outputs "x", where x is an integer.
private Semaphore s0 = new Semaphore(1);
private Semaphore s1 = new Semaphore(0);
private Semaphore s2 = new Semaphore(0);
public void zero(IntConsumer printNumber) throws InterruptedException {
for (int i = 1; i <= n; i++) {
s0.acquire();
printNumber.accept(0);
if (i % 2 == 1) s1.release();
else s2.release();
}
}

public void odd(IntConsumer printNumber) throws InterruptedException {
for (int i = 1; i <= n; i += 2) {
s1.acquire();
printNumber.accept(i);
s0.release();
}
}

public void even(IntConsumer printNumber) throws InterruptedException {
for (int i = 2; i <= n; i += 2) {
s2.acquire();
printNumber.accept(i);
s0.release();
}
}
}