Semaphore 信號量

java.util.concurrent.Semaphore.Semaphore(int permits)

構造函數,指定許可證的數量。代表共享資源的個數。可以設爲0.也可以設爲負數。

void java.util.concurrent.Semaphore.acquire() throws InterruptedException

從信號量中獲得一個許可證。若得不到會被阻塞,直到有一個許可證可用。


void java.util.concurrent.Semaphore.release()

釋放一個許可證,還給信號量。


筆記摘要:

               這裏主要介紹了java5中線程鎖技術以外的其他同步工具,首先介紹semaphore:一個計數信號量。用於控制同時訪問資源的線程個數,

               CyclicBarrier同步輔助類:從字面意思看是路障,這裏用於線程之間的相互等待,到達某點後,繼續向下執行,CountDownLatch同步輔

              助類:在完成一組正在其他線程中執行的操作之前,它允許一個或多個線程一直等待。猶如倒計時計數器,然後是Exchangeer:實現兩個

             對象之間數據交換,可阻塞隊列:ArrayBlockingQueue,通過阻塞隊列間的通信來演示其作用,最後介紹了幾個同步集合。



一、Semaphore實現信號燈


        1.、Semaphore可以維護當前訪問自身的線程個數,並提供了同步機制,使用Semaphore可以控制同時訪問資源的線程個數,例如,實現一個文件允許

       的併發訪問數。Semaphore 只對可用許可的號碼進行計數,並採取相應的行動。 

   

        2、Semaphore實現的功能就像:銀行辦理業務,一共有5個窗口,但一共有10個客戶,一次性最多有5個客戶可以進行辦理,其他的人必須等候,

     當5客戶中的任何一個離開後,在等待的客戶中有一個人可以進行業務辦理。


        3、Semaphore提供了兩種規則:

               一種是公平的:獲得資源的先後,按照排隊的先後。在構造函數中設置true實現

               一種是野蠻的:誰有本事搶到資源,誰就可以獲得資源的使用權。


       4、與傳統的互斥鎖的異同:

             單個信號量的Semaphore對象可以實現互斥鎖的功能,並且可以是由一個線程獲得了“鎖“,再由另外一個線程釋放”鎖“,

       這可以應用於死鎖恢復的一些場合。


      5、應用場景:共享資源的爭奪,例如遊戲中選手進入房間的情況。


  1. import java.util.concurrent.ExecutorService;  
  2. import java.util.concurrent.Executors;  
  3. import java.util.concurrent.Semaphore;  
  4.   
  5. public class SemaphoreTest {  
  6.     public static void main(String[] args) {  
  7.           
  8.   //創建一個可根據需要創建新線程的線程池  
  9.   ExecutorService service = Executors.newCachedThreadPool();  
  10.         final  Semaphore sp = new Semaphore(3);  
  11.           
  12.   //創建10個線程  
  13.   for(int i=0;i<10;i++){  
  14.             Runnable runnable = new Runnable(){  
  15.                     public void run(){  
  16.                     try {  
  17.                         sp.acquire();   //獲取燈,即許可權  
  18.                     } catch (InterruptedException e1) {  
  19.                         e1.printStackTrace();  
  20.                     }  
  21.                     System.out.println("線程" + Thread.currentThread().getName() +   
  22.                             "進入,當前已有" + (3-sp.availablePermits()) + "個併發");  
  23.                     try {  
  24.                         Thread.sleep((long)(Math.random()*10000));  
  25.                     } catch (InterruptedException e) {  
  26.                         e.printStackTrace();  
  27.                     }  
  28.                     System.out.println("線程" + Thread.currentThread().getName() +   
  29.                             "即將離開");                      
  30.                     sp.release();   // 釋放一個許可,將其返回給信號量  
  31.   
  32.                     //下面代碼有時候執行不準確,因爲其沒有和上面的代碼合成原子單元  
  33.                     System.out.println("線程" + Thread.currentThread().getName() +   
  34.                             "已離開,當前已有" + (3-sp.availablePermits()) + "個併發");                      
  35.                 }  
  36.             };  
  37.             service.execute(runnable);            
  38.         }  
  39.     }  
  40.   
  41. }  

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