Semaphore类是java.util.concurrent包的一个并发工具栏,是一个计数信号量,必须由获取它的线程释放,常用于限制访问某些资源的线程数量,例如限流。
Semaphore的构造方法有两种,如下:
/**
*
* @param permits 表示许可数目,即同时可以允许多少线程进行访问
* @param fair 表示是否是公平的,即等待时间越久的越先获得许可
*/
public Semaphore(int permits, boolean fair) {
...
}
public Semaphore(int permits) {
...
}
Semaphore可以控制同时访问的线程个数,通过acquire()
函数获取一个许可,如果没有就等待。获取许可之后,可通过release()
函数再释放许可。这两个函数都有两种使用方式,如下:
/**
* 尝试获取一个许可,
*
* @throws InterruptedException
*/
public void acquire() throws InterruptedException {
...
}
/**
* 获取peimits个许可
*
* @param permits
* @throws InterruptedException
*/
public void acquire(int permits) throws InterruptedException {
...
}
/**
* 释放一个许可
*/
public void release() {
...
}
/**
* 释放permits个许可
*
* @param permits
*/
public void release(int permits) {
...
}
以上四个方法都会被阻塞,如果想立即得到执行结果或增加超时机制,可使用下面的方法:
/**
* 尝试获取一个许可,若获取成功,则立即返回true,否则立即返回false
*
* @return
*/
public boolean tryAcquire() {
...
}
/**
* 尝试获取一个许可,若在指定的时间内获取成功,则返回true,否则返回false
*
* @param timeout 超时时间
* @param unit 时间单位
* @return
* @throws InterruptedException
*/
public boolean tryAcquire(long timeout, TimeUnit unit)
throws InterruptedException {
...
}
/**
* 尝试获取多个许可,若获取成功,则立即返回true,否则立即返回false
*
* @param permits 请求许可数量
* @return
*/
public boolean tryAcquire(int permits) {
...
}
/**
* 尝试获取多个许可,若在指定时间内成功,则返回true,否则返回false
*
* @param permits 请求许可数量
* @param timeout 超时时间
* @param unit 时间单位
* @return
* @throws InterruptedException
*/
public boolean tryAcquire(int permits, long timeout, TimeUnit unit)
throws InterruptedException {
...
}
Semaphore其实和锁有点类似,一般用于控制对某组资源的访问权限。例如有5个工人使用3个工具完成工作,就需要先有3个人拿工具工作,其余2个人等待,直到前3个人有人释放工具,这2个人再获取工具继续完成工作。示例代码如下:
public class WorkerThread {
private Semaphore semaphore;
private int id;
public WorkerThread(int id, Semaphore semaphore) {
this.id = id;
this.semaphore = semaphore;
}
public void function() {
try {
System.out.println("The Worker " + this.id + " prepares to takes a tool.");
Thread.sleep(1000);
semaphore.acquire();
System.out.println("The Worker " + this.id + " takes a tool to finish his job.");
Thread.sleep(2000);
semaphore.release();
System.out.println("The Worker " + this.id + " released a tool.");
} catch (Exception e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) throws InterruptedException {
// 工人数量
int num = 5;
// 工具数量
Semaphore semaphore = new Semaphore(3);
for (int i = 0; i < num; i++) {
new Thread(new WorkerThread(i, semaphore)::function).start();
}
}
输出结果如下: