多線程執行時,若是一個邏輯須要等若干個線程執行完成後再執行,怎麼實現?

實際開發過程當中,尤爲是大型的業務系統中或批量處理系統中,咱們一般會用到多線程來進行任務拆分,來提升系統的處理能力。當對業務不斷拆分時,多線程各自任務之間也造成了錯綜複雜的關係。多線程

咱們經常遇到這樣的狀況,業務模塊A 拆分紅了 A1 、A2.....An個多線程,來提升處理速度,但是 Ak(1<k<n)這個線程執行時,它有依賴關係,它必須等 Ak-1 和Ak-2這兩個進程執行完,才能執行,以避免形成業務混亂,那怎麼實現?ide

咱們先定義兩個實現多線程任務:函數

任務1:this

public class WorkA1 extends Thread {
   @Override
   public void run() {
      System.out.println("WorkA1 開始執行");
      try {
         Thread.sleep(2000);
      } catch (InterruptedException e) {
         e.printStackTrace();
      }
      System.out.println("WorkA1 結束執行");
   }
}

任務2:spa

public class WorkA2 extends Thread {
   @Override
   public void run() {
      System.out.println("WorkA2 開始執行");
      try {
         Thread.sleep(1800);
      } catch (InterruptedException e) {
         e.printStackTrace();
      }
      System.out.println("WorkA2 結束執行");
   }
}

主線程開始實現是這樣的:線程

public class ThreedClient {
   public static void main(String[] args) {
      System.out.println("準備開始執行任務");
      WorkA1 workA1 = new WorkA1();
      WorkA2 workA2 = new WorkA2();
      workA1.start();
      workA2.start();
      System.out.println("執行完成了。");
   }
}

執行結果是:進程

準備開始執行任務
執行完成了。
WorkA1 開始執行
WorkA2 開始執行
WorkA2 結束執行
WorkA1 結束執行

若是咱們想最後打印 「執行完成了」在全部子線程完成後,怎麼辦呢?開發

咱們對主線程進行改造:it

改造方法1:io

public class ThreedClient {
   public static void main(String[] args) {
      System.out.println("準備開始執行任務");
      WorkA1 workA1 = new WorkA1();
      WorkA2 workA2 = new WorkA2();
      workA1.start();
      workA2.start();
      try {
         workA1.join();
         workA2.join();
      }catch (InterruptedException e){
         e.printStackTrace();
      }
      System.out.println("執行完成了。");
   }
}

改造完成後,在看執行結果:

準備開始執行任務
      WorkA2 開始執行
      WorkA1 開始執行
      WorkA2 結束執行
      WorkA1 結束執行
      執行完成了。

OK,達到咱們的預期了。

改造方法2:

CountDownLatch容許一個或多個線程等待其餘線程完成操做。CountDownLatch的構造函數接收一個int類型的參數做爲計數器,若是你想等待N個點完成,這裏就傳入N。當咱們調用countDown方法時,N就會減1,await方法會阻塞當前線程,直到N變成0。
它的原理很簡單,就是你須要等待幾個任務時,就先定義好,而後任務執行完成一個,計數器減1。看看具體實現:
public class WorkA1 extends Thread {
   private CountDownLatch countDownLatch;
   public WorkA1(CountDownLatch countDownLatch) {
      this.countDownLatch = countDownLatch;
   }
   @Override
   public void run() {
      System.out.println("WorkA1 開始執行");
      try {
         Thread.sleep(2000);
      } catch (InterruptedException e) {
         e.printStackTrace();
      }finally {
         countDownLatch.countDown();
      }
      System.out.println("WorkA1 結束執行");
   }
}

Work2的改造跟Work1徹底同樣,就再也不單獨貼代碼了。

看下主線程中的改造:

public class ThreedClient {
   public static void main(String[] args) {
      System.out.println("準備開始執行任務");
      CountDownLatch countDownLatch = new CountDownLatch(2);
      WorkA1 workA1 = new WorkA1(countDownLatch);
      WorkA2 workA2 = new WorkA2(countDownLatch);
      workA1.start();
      workA2.start();
      try {
         countDownLatch.await();
      }catch (InterruptedException e){
         e.printStackTrace();
      }
      System.out.println("執行完成了。");
   }
}

 咱們看下改造後的執行結果:

準備開始執行任務
WorkA1 開始執行
WorkA2 開始執行
WorkA2 結束執行
WorkA1 結束執行
執行完成了。

跟改造1中的效果如出一轍。

相關文章
相關標籤/搜索