分类: Java技术

Semaphore)是实现多线程同步的两种常用的手段。信号量需要初始化一个许可值,许可值可以大于0,也可以小于0,也可以等于0.

     如果大于0,表示,还有许可证可以发放,线程不会被阻塞;

     如果小于或者等于0,表示,没有许可证可以发放了,线程被阻塞住了。

acquire()申请许可证,如果有,就可以获得,如果没有就等待了。

                         release(),归还许可证,保证循环使用。



     看一个例子,就会明白了,还是实现上次的那个生产者和消费者的例子。

     我们假设有一个篮子,最多可以放3个苹果,有多个人可以放苹果,也有多个人可以拿走苹果。


public class Apple {

private String name;

public Apple(String name){

this. name= name;

    }

@Override

public String toString() {

// TODO Auto-generated method stub

return name ;

       }


}


public class Basket {
	
private List bascket =new ArrayList(10);
	
mutex = new Semaphore(1);
	
isFull = new Semaphore(10);
	
       
	
isEmpty = new Semaphore(0);
	
       
	
public void put(Apple app) throws InterruptedException{
	
//大于0,就放行
	
//acquire,就是减操作,如果小于0,就阻塞
	
//release,就是加操作,如果大于0,就不会被阻塞
	
isFull. acquire();
	
try{
	
mutex. acquire();
	
bascket.add( app);
	
              }
	
finally{
	
mutex.release();
	
isEmpty.release();
	
              }
	
       }
	
       
	
public Apple take() throws InterruptedException{
	
app;
	
isEmpty. acquire();
	
try{
	
mutex. acquire();
	
app= bascket.remove(0);
	
              }
	
finally{
	
mutex.release();
	
isFull.release();
	
              }
	
return app ;
	
       }
	

}
	

//消费者
		
publicclass Consumer implements Runnable{
		
privateBasket bascket ;
		
privateString name ;
		
publicConsumer(Basket bascket ,String name ){
		
this.bascket =bascket ;
		
this.name =name ;
		
       }
		
publicvoid run(){
		
while(true ){
		
try{
		
out.println(name +":consumer" +bascket .take());
		
catch(InterruptedExceptione1) {
		
// TODO Auto-generated catch block
		
e1.printStackTrace();
		
                     }
		
try{
		
sleep(1000);
		
catch(InterruptedException e ) {
		
// TODO Auto-generated catch block
		
e.printStackTrace();
		
                     }
		
              }
		
       }
		

}
		

//生产者
			
publicclass Producer implements Runnable{
			
privateBasket bascket ;
			
privateString name ;
			
publicProducer(Basket bascket ,String name ){
			
this.bascket =bascket ;
			
this.name =name ;
			
       }
			
publicvoid run(){
			
              
			
while(true ){
			
try{
			
out.println(name +"produce.." );
			
bascket. put(new"name"+new Random()));
			
catch(InterruptedExceptione) {
			
// TODO Auto-generated catch block
			
e.printStackTrace();
			
                     }
			
try{
			
sleep(1000);
			
catch(InterruptedException e ) {
			
// TODO Auto-generated catch block
			
e.printStackTrace();
			
                     }
			
                     
			
              }
			
              
			
       }
			

}
			

publicclass TestDemo {
				
publicstatic voidargs[]){
				
bascket= newBasket();
				
c1= newConsumer(bascket ,"c1" );
				
              
				
p1= newProducer(bascket ,"p1" );
				
p2= newProducer(bascket ,"p2" );
				
              
				
//线程池管理
				
servicenewCachedThreadPool();
				
service.execute( c1);
				
service.execute( p1);
				
service.execute( p2);
				
       }
				
}


一定要注意,上面acquire的顺序,如果不正确,所有的线程就会被阻塞了。

信号量的实现原理会在源代码中进行分析。