一、介绍
Semaphore是一种基于计数的信号量。它可以设定一个阈值,基于此,多个线程竞争获取许可信号,做自己的申请后归还,超过阈值后,线程申请许可信号将会被阻塞。Semaphore可以用来构建一些对象池,资源池之类的,比如数据库连接池,我们也可以创建计数为1的Semaphore,将其作为一种类似互斥锁的机制,这也叫二元信号量,表示两种互斥状态。
它的用法如下:
availablePermits 函数用来获取当前可用的资源数量
wc.acquire(); //申请资源
wc.release();// 释放资源
二、模拟测试
1. 需求:
假设:有10个患者去就诊,但医生只有3人,所以只能有3个患者能同时就诊(也就是只能有三个线程能同时执行一段代码)
2. 运行结果:
3. Java代码:
package com.example.demo.thread;
import java.util.Random;
import java.util.concurrent.Semaphore;
/**
* @Description 信号量
* @author 大都督
* @date 2019年5月1日
*/
public class SemaphoreTest {
//内部类
public class patient implements Runnable{
private String code;//患者编号
private Semaphore doctors;//医生信号量
public patient(String code, Semaphore doctors) {//构造函数
this.code = code;
this.doctors = doctors;
}
@Override
public void run() {//重写run方法
try {
// 空闲的医生数量
int availablePermits = doctors.availablePermits();
if (availablePermits > 0) {
System.out.println("患者编号:" + code + ", 正在准备就诊");
}else {
System.out.println("患者编号:" + code + ", 正在等待就诊");
}
// 申请医生,如果三个医生都在给患者看病,则患者就等待
doctors.acquire();
System.out.println("患者编号:" + code + ", 看病中...");
Thread.sleep(new Random().nextInt(1000)); // 模拟看病时间。
System.out.println("患者编号:" + code + ", 看病完成");
doctors.release();//释放医生
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public static void main(String[] args) {
SemaphoreTest semaphoreTest = new SemaphoreTest();
// 创建资源,三个医生
Semaphore doctors = new Semaphore(3);
// 十个患者看病,占用医生资源
for (int i = 1; i <= 10; i++) {
patient patient = semaphoreTest.new patient("患者" + i, doctors);
new Thread(patient).start();
}
}
}
4. 一些说明:
a) 内部类的调用
b) 实现Runnable接口的线程,开启方式
c)doctors.acquire(); // 申请医生,如果三个医生都在给患者看病,则患者就等待
d)doctors.release();//释放医生