1. 程式人生 > >Java併發程式設計藝術 8 Java中的併發工具類

Java併發程式設計藝術 8 Java中的併發工具類

第8章 Java中的併發工具類 併發工具類中主要提供了一些併發流程控制的手段。主要有CountDownLatch、CyclicBarriery和Semaphore Exchanger工具類提供線上程間交換資料的一種手段。 CountDownLatch  CountDownLatch類能夠使一個執行緒進行等待,等待其他相關的執行緒完成各自的任務以後再執行當前執行緒的工作。 例如:一個程式的主執行緒希望負責啟動框架的所有主執行緒完成以後再繼續執行。 CountDownLatch是通過一個計數器來實現的,計數器的初始值就是相關執行緒的數量。當每一個相關執行緒完成任務的時候,對計數器的值減1。當計數器的值到達0時,他表示所有的相關執行緒已經完成了任務。然後使用CountDownLatch閉鎖上等待的執行緒可以繼續執行任務。(建議將countDown()放在finally裡執行) 1.主執行緒執行緒開始 2.在主執行緒中建立一個CountDownLatch,根據N個相關執行緒。CountDownLatch初始值為N。 3.主執行緒使用await,在CountDownLatch上等待 4.相關執行緒完成任務後,對CountDownLatch減1.  countDown()。 5.當CountDownLatch為0時,主執行緒繼續執行。 CountDownLatch的三個基本元素
CountDownLatch latch = new CountDownLatch(5); //主執行緒 latch.await() latch.countDown() //子執行緒
CountDownLatch物件內部計數器的值只能被初始化一次,必能重新初始化。一旦賦值以後,以為能修改計數的方法就是countDown()方法,對內部計數器減1。 當計數器到達0時, 全部呼叫 await() 方法會立刻返回,接下來任何countDown() 方法的呼叫都將不會造成任何影響。 總結: CountDownLatch是同步工具類中的一種。可以使一個執行緒進行等待,直到其他執行緒執行完畢後再執行當前執行緒。是通過內部計數器來實現的,每完成一個任務就對計數器進行減1。直到為0,閉鎖等待的執行緒就可以恢復執行。
可以用來實現執行緒等待和最大並行性。
CyclicBarriery CyclicBarriery的預設構造方法CyclicBarrier(int parties),初始化引數表示屏障攔截的執行緒數。 當每一個執行緒呼叫await的時候通知CyclicBarrier已經到達屏障,然後當前執行緒被阻塞在await()方法上。 等到攔截到初始化時設定的執行緒數時,所有執行緒繼續執行,之後再執行await()不會再等待。如果沒有攔截到指定數量的執行緒,這全部都阻塞。 CyclicBarriery還提供了更高階的構造,可以傳入barrierAction(Runnable型別),當所有執行緒到達屏障時,優先執行barrierAction。可以用作所有屏障到達的一個通知點
static CyclicBarrier b = new CyclicBarrier(10); static CyclicBarrier b = new CyclicBarrier(10,new Runnable() {      public void run() {            System.out.println("hahhha");      } }); public static void main(String[] args) throws InterruptedException, BrokenBarrierException {      for(int i=0;i<10;i++){            new Thread(new MRunnable()).start();      }      b.await();      System.out.println("main");      b.reset();      b.await();      System.out.println("main"); } static class MRunnable implements Runnable{      public void run() {            try {                 Thread.sleep(5000);                 System.out.println("MRunnanle1 ");                 b.await();            } catch (InterruptedException | BrokenBarrierException e) {                 e.printStackTrace();            }
     }
} 實現最大的並行性:有時我們想同時啟動多個執行緒,實現最大程度的並行性。 開始執行前等待n個執行緒完成各自任務:例如應用程式啟動類要確保在處理使用者請求前,所有N個外部系統已經啟動和運行了。 通過將await()放在任務前還是任務後,來實現以上兩種功能。 CountDownLatch 和CyclicBarrier區別 【1】.CountDownLatch計數器只能使用一次,CyclicBarrier的計數器可以通過reset()重置。 【2】CyclicBarrier中還提供了getNumberWaiting()方法獲取阻塞的執行緒數。,以及一些其他方法。 【3】CountDownLatch使用減計數方式,從指定值開始減,減到為0釋放所有執行緒。CyclicBarrier使用加計數方式,從0開始加到指定值釋放所有執行緒 【4】CountDownLatch 的await()只負責阻塞,使用CountDown()方法減一。CyclicBarrier的await(),負責阻塞,並且對計數加一。 Semaphore Semaphore(訊號量)用於控制同時訪問特定資源的執行緒數量,可以協調各個執行緒保證合理的使用公共資源。 比如:訪問共享檔案,只允許最多十個執行緒同時訪問。比如資料庫連線,最多支援十個執行緒連線。 static Semaphore s = new Semaphore(10); public static void main(String[] args) throws InterruptedException {      for(int i=0;i<30;i++){            new Thread(new MyRunnabe()).start();      }      Thread.sleep(2000);      System.out.println(s.availablePermits());      System.out.println(s.getQueueLength());      while(true){            if (s.getQueueLength()==0) {                 break;            }            System.out.println("in waiting thread : "+s.getQueueLength());            Thread.sleep(5000);      } } static class MyRunnabe implements Runnable{      public void run() {            try {                 s.acquire();                 System.out.println("out");                 Thread.sleep(10000);
                s.release();            } catch (InterruptedException e) {                 e.printStackTrace();            }
     } } int availablePermits()  放回訊號量中可用的許可證數量 int getQueueLength()    返回正在等待獲取許可證的執行緒數 boolean  hasQueuedThread() 當前是否有執行緒正在等待許可證 void  reducePermits()  減少許可證數量,是protected方法 Collection getQueuedThreads()  返回所有等待的獲取許可證的執行緒集合,是protected方法。 Exchanger 執行緒間交換資料。Exchanger(交換者)是執行緒間協作的工具類。用於執行緒之間的資料交換。 提供一個同步點,實現兩個執行緒之間的資料交換。當一個執行緒執行了exchange方法,會等待另個執行緒執行exchange方法。當兩個執行緒同時到達同步點就可以交換資料,將本執行緒的資料傳遞給對方。