九、併發工具類之Semaphore

流量控制 Semaphore

Semaphore是一個計數的信號量。初始化時分配一個配額permits。在訪問前需要用acquire()方法申請一個配額,訪問結束後調用release()釋放配置。申請配額時如果配額不足將會阻塞。

例子:有2個足球,4個人射門練習。每個人射門後都要把球拿回來,後面的人才能射球。

public class Player implements  Runnable {

    private final Semaphore semaphore;

    public Player(Semaphore semaphore){
        this.semaphore=semaphore;
    }
    public void run() {
        try {
            semaphore.acquire();
            //踢完還剩餘的球
            System.out.println("踢球。。。。"+semaphore.availablePermits());
            int millis = new Random().nextInt(4)+1;
            Thread.sleep(millis*1000);
            System.out.println(String.format("撿球花時間%d秒",millis));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            semaphore.release();
        }
    }
}


  public  static  void main(String[] args){

        Semaphore semaphore = new Semaphore(2);

        for(int i=0;i<4;i++){
            new Thread(new Player(semaphore)).start();
        }

        try {
            Thread.sleep(1000000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }

結果

踢球。。。。1
踢球。。。。0
撿球花時間4秒
撿球花時間4秒
踢球。。。。0
踢球。。。。0
撿球花時間1秒
撿球花時間2秒

 

  1. Semaphore內部是由共享鎖實現的。
  2. Semaphore支持公平鎖和非公平鎖。默認是非公平鎖。可以通過構造函數設置。

常用API

void acquire() 
從該信號量獲取許可證,阻止直到可用,或線程爲 interrupted 。  
void acquire(int permits) 
從該信號量獲取給定數量的許可證,阻止直到所有可用,否則線程爲 interrupted 。  
void acquireUninterruptibly() 
從這個信號燈獲取許可證,阻止一個可用的。  
void acquireUninterruptibly(int permits) 
從該信號量獲取給定數量的許可證,阻止直到所有可用。  
int availablePermits() 
返回此信號量中當前可用的許可數。  
int drainPermits() 
獲取並返回所有可立即獲得的許可證。  
protected Collection<Thread> getQueuedThreads() 
返回一個包含可能正在等待獲取的線程的集合。  
int getQueueLength() 
返回等待獲取的線程數的估計。  
boolean hasQueuedThreads() 
查詢任何線程是否等待獲取。  
boolean isFair() 
如果此信號量的公平設置爲真,則返回 true 。  
protected void reducePermits(int reduction) 
縮小可用許可證的數量。  
void release() 
釋放許可證,將其返回到信號量。  
void release(int permits) 
釋放給定數量的許可證,將其返回到信號量。  
String toString() 
返回一個標識此信號量的字符串及其狀態。  
boolean tryAcquire() 
從這個信號量獲得許可證,只有在調用時可以使用該許可證。  
boolean tryAcquire(int permits) 
從這個信號量獲取給定數量的許可證,只有在調用時全部可用。  
boolean tryAcquire(int permits, long timeout, TimeUnit unit) 
從該信號量獲取給定數量的許可證,如果在給定的等待時間內全部可用,並且當前線程尚未 interrupted 。  
boolean tryAcquire(long timeout, TimeUnit unit) 
如果在給定的等待時間內可用,並且當前線程尚未 到達 interrupted,則從該信號量獲取許可。  

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章