信号量机制通常用于限制对某种资源的同时访问的线程数量。信号量机制是一中典型的同步机制,可以用于解决常用的线程同步问题。
在java并发库中,类Semaphore可以实现信号量机制。定义如下
public class Semaphore extends Object implements Serializable
一个信号量管理一个许可集合,可以通过方法acquire()获取一个许可,如果没有许可可以使用,则等待。通过方法release()可以释放一个许可。
信号量的构造方法如下:
Semaphore( int permits) ;//用给点给的许可数来创建一个Samephore对象。
Semaphore(in permits,boolean fair)//用给定的许可数,创建Samephore对象,并可以设置公平参数fair。参数fair可以取值为true或false,指明当有许可使用时,是采用公平策略还是非公平策略来获取许可,
公平策略可以保证每个都能获取许可,对于防止线程出现“饥饿”现象是由帮助的。
例如:
Semaphore available = new Semaphore(10,true); //表示创建了有是个许可的信号量 available,该信号量的获取策略是公平的。
Semaphore available = new Semaphore(1);//表示创建了只有一个许可的信号量,它可以实现互拆锁的功能。
1)demo 示例:
银行有4个窗口可以同时办理业务,现在有20个顾客需要办理业务,使用信号量机制模拟。
//工作线程类
public class Customer extends Thread{
Semaphore counter;
int id;
int times;
Coustomer (Semaphore counter,int id){
this.counter = counter;
this.id = id;
times = (int)(Math.random() *Integer.MAX_VALUE);
}
public void run(){
try{
counter.acquire(); //获取许可
System.out.println("第"+id + "尾顾客开始办理业务>>>>>>");
for(int i=0;i<times;i++); //模拟了顾客办理业务的时间。。。
System.out.println("第"+ id+ "位顾客已经办理完业务,准备离开>>>>>>");
counter.release();
}catch(InterruptedException e){
e.printStackTrace();
}
}
}
//启动类
public class Index{
public static void main(String [] args){
Semaphore counter = new Semaphore(4);
Thread [] threads = new Thread[20];
for(int i = 0;i<20;i++){
threads[i] = new Coustomer(counter,i+1);
threads[i].start();
}
}
}
运行结果:
第1位顾客开始办理业务>>>>>>
第4位顾客开始办理业务>>>>>>
第2位顾客开始办理业务>>>>>>
第3位顾客开始办理业务>>>>>>
第2位顾客已经办理完业务,准备离开>>>>>>
第4位顾客已经办理完业务,准备离开>>>>>>
第3位顾客已经办理完业务,准备离开>>>>>>
第5位顾客开始办理业务>>>>>>
第6位顾客开始办理业务>>>>>>
第7位顾客开始办理业务>>>>>>
第6位顾客已经办理完业务,准备离开>>>>>>
第5位顾客已经办理完业务,准备离开>>>>>>
第1位顾客已经办理完业务,准备离开>>>>>>
第7位顾客已经办理完业务,准备离开>>>>>>
第8位顾客开始办理业务>>>>>>
第9位顾客开始办理业务>>>>>>
第10位顾客开始办理业务>>>>>>
第10位顾客已经办理完业务,准备离开>>>>>>
第8位顾客已经办理完业务,准备离开>>>>>>
第9位顾客已经办理完业务,准备离开>>>>>>
第11位顾客开始办理业务>>>>>>
第14位顾客开始办理业务>>>>>>
第13位顾客开始办理业务>>>>>>
第13位顾客已经办理完业务,准备离开>>>>>>
第12位顾客开始办理业务>>>>>>
第15位顾客开始办理业务>>>>>>
第14位顾客已经办理完业务,准备离开>>>>>>
第11位顾客已经办理完业务,准备离开>>>>>>
第16位顾客开始办理业务>>>>>>
第16位顾客已经办理完业务,准备离开>>>>>>
第15位顾客已经办理完业务,准备离开>>>>>>
第12位顾客已经办理完业务,准备离开>>>>>>
第18位顾客开始办理业务>>>>>>
第19位顾客开始办理业务>>>>>>
第19位顾客已经办理完业务,准备离开>>>>>>
第17位顾客开始办理业务>>>>>>
第18位顾客已经办理完业务,准备离开>>>>>>
第20位顾客开始办理业务>>>>>>
第17位顾客已经办理完业务,准备离开>>>>>>
第20位顾客已经办理完业务,准备离开>>>>>>
2)demo 示例:
使用信号量 使用只有一个许可的信号量作为锁,实现同步控制。
public class Data{
int a = 0;
int b = 0;
Semaphore semaphore;
Data( Semaphore semaphore){
this.semaphore = semaphore;
}
//增加1
public void increase(){
try{
semaphore.acquire();
a++;
b++;
}catch(InterruptedException e){
e.printStackTrace();
}
semaphore.release();
}
//验证
public void isEqual(){
try{
semaphore.acquire();
System.out.println("a = " + a + "\tb" + "b = " + b + "\t" + (a==b) );
}catch(InterruptedException e){
e.printStackTrace();
}
semaphore.release();
}
}
//线程工作类
public class Worker implements Runnable{
private Data data;
Worker(Data data){
this.data = data;
}
public void run(){
while(true){
data.increase();
}
}
//启动类
public class Index{
public static void main(String [] args){
Semaphore semaphore = new Semaphore(1);
Data data = new Data( semaphore );
Worker worker1 = new Worker( data);
Worker worker2 = new Worker(data);
Thread t1 = new Thread( worker1);
Thread t2 = new Thread( worker2);
t1.start();
t2.start();
while(true){
data.isEqual();
try{
Thread.sleep(1000);
}catch(InterruptedException e){
e.printStackTrace();
}
}
}
}
运行结果:
a = 0 b = 0 true
a = 26223538 b = 26223538 true
a = 51329669 b = 51329669 true
a = 77307542 b = 77307542 true
a = 102215781 b = 102215781 true
a = 127411276 b = 127411276 true
a = 152337489 b = 152337489 true
a = 178239099 b = 178239099 true