Semaphore
Semaphore 是一种基于技术的信号量。它可以设置一个阈值,然后多个线程竞争获取许可信号,完成后归还,超过阈值后,线程申请许可信号将会被阻塞。
常用方法
- Semaphore(int permits) 参数permits表示许可数目,即同时可以允许多少线程进行访问
- Semaphore(int permits, boolean fair) 多了一个参数fair表示是否是公平的,即等待时间越久的越先获取许可
- availablePermits() 返回此信号量中当前可用的许可数。
- acquire() 申请资源
- release() 释放资源
用法
Semaphore semp = new Semaphore(5);
try {
// 申请许可
semp.acquire();
try {
// 业务逻辑
} catch (Exception e) {
} finally {
// 释放许可
semp.release();
}
} catch (InterruptedException e) {
}
案例
在公共厕所只有3个坑位,但是有10个人来上厕所。那怎么办?
假设10个人的编号分别为1-10,谁先到达,谁先抢到厕所坑位,谁就上厕所。一个坑位就是一个资源,只能一个人单独上厕所,一个线程使用一个资源,不能共享。
package cn.lvhaosir;
import java.util.Random;
import java.util.concurrent.Semaphore;
class Parent implements Runnable {
String name;
Semaphore semaphore;
public Parent(String name, Semaphore semaphore) {
super();
this.name = name;
this.semaphore = semaphore;
}
@Override
public void run() {
// 获取到资源权限,减去1,坑位减1
int availablePermits = semaphore.availablePermits();
if(availablePermits > 0) {
// 还有资源,还有坑位
System.out.println(name+"还有坑位...");
} else {
// 没有资源了
System.out.println(name+"怎么没有坑位了...");
}
try {
// 申请资源,没有申请到的,就在此等待。有资源就继续向下执行。
semaphore.acquire();
// 模拟执行步骤和所需时间
System.out.println(name+"终于进入坑位...");
Thread.sleep(new Random().nextInt(1000));
System.out.println(name+"上完了...");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
// 释放资源,坑位空出来了
semaphore.release();
}
}
}
public class Test004 {
public static void main(String[] args) throws InterruptedException {
// 只有3个资源,3个坑位
Semaphore semaphore = new Semaphore(3);
for (int i = 1; i <= 10; i++) {
new Thread(new Parent("第"+i+"个", semaphore)).start();;
}
}
}