實際開發過程當中,尤爲是大型的業務系統中或批量處理系統中,咱們一般會用到多線程來進行任務拆分,來提升系統的處理能力。當對業務不斷拆分時,多線程各自任務之間也造成了錯綜複雜的關係。多線程
咱們經常遇到這樣的狀況,業務模塊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:
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中的效果如出一轍。