Java信号量Semaphore原理及代码实例
Semaphore通常用于限制可以访问某些资源(物理或逻辑的)的线程数目。自从5.0开始,jdk在java.util.concurrent包里提供了Semaphore的官方实现,因此大家不需要自己去实现Semaphore。
下面的类使用信号量控制对内容池的访问:
importjava.util.concurrent.Semaphore;
classPool{
privatestaticfinalintMAX_AVAILABLE=100;
privatefinalSemaphoreavailable=newSemaphore(MAX_AVAILABLE,true);
publicObjectgetItem()throwsInterruptedException{
available.acquire();//从此信号量获取一个许可,在提供一个许可前一直将线程阻塞,否则线程被中断
returngetNextAvailableItem();
}
publicvoidputItem(Objectx){
if(markAsUnused(x))
available.release();//释放一个许可,将其返回给信号量
}
//仅作示例参考,非真实数据
protectedObject[]items=null;
protectedboolean[]used=newboolean[MAX_AVAILABLE];
protectedsynchronizedObjectgetNextAvailableItem(){
for(inti=0;i
虽然JDK已经提供了相关实现,但是还是很有必要去熟悉如何使用Semaphore及其背后的原理。
做一个简单的Semaphore实现:
classSemaphoreTest{
privatebooleansignal=false;
publicsynchronizedvoidtake(){
this.signal=true;
this.notify();
}
publicsynchronizedvoidrelease()throwsInterruptedException{
while(!this.signal)
wait();
this.signal=false;
}
}
使用这个semaphore可以避免错失某些信号通知。用take方法来代替notify,release方法来代替wait。如果某线程在调用release等待之前调用take方法,那么调用release方法的线程仍然知道take方法已经被某个线程调用过了,因为该Semaphore内部保存了take方法发出的信号。而wait和notify方法就没有这样的功能。
可计数的Semaphore:
classSemaphoreTest{
privateintsignals=0;
publicsynchronizedvoidtake(){
this.signals++;
this.notify();
}
publicsynchronizedvoidrelease()throwsInterruptedException{
while(this.signals==0)
wait();
this.signals--;
}
}
Semaphore上限:
classSemaphoreTest{
privateintsignals=0;
privateintbound=0;
publicSemaphoreTest(intupperBound){
this.bound=upperBound;
}
publicsynchronizedvoidtake()throwsInterruptedException{
while(this.signals==bound)
wait();
this.signals++;
this.notify();
}
publicsynchronizedvoidrelease()throwsInterruptedException{
while(this.signals==0)
wait();
this.signals--;
this.notify();
}
}
当已经产生的信号数量达到了上限,take方法将阻塞新的信号产生请求,直到某个线程调用release方法后,被阻塞于take方法的线程才能传递自己的信号。
把Semaphore当锁来使用:
当信号量的数量上限是1时,Semaphore可以被当做锁来使用。通过take和release方法来保护关键区域。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。