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方法来保护关键区域。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。