多線程 - CountDownLatch總結

問題

當主線程的任務執行,需要依賴多個子線程運行結束後才能往下執行時如何解決,比如文件分段下載,同時開啓多個子線程進行文件的分段下載,當下載完成之後,再進行組裝。

有一種解決方式,便是在子線程下載完成之後,都進行子線程的回調並判斷是否所有子線程都已經執行完畢。

CountDownLatch便是java在1.5提供的解決如上問題的工具類

阿里的ARouter的攔截器相關,就是用該工具類

概述

CountDownLatch是通過一個計數器來實現的,計數器的初始值是線程的數量。然後通過調用await()完成阻塞,每當一個線程執行完畢後,計數器的值就-1,當計數器的值爲0時,表示所有線程都執行完畢,然後阻塞會被打開。

使用

初始化CountDownLatch並設置子線程數量

CountDownLatch latch = new CountDownLatch(2);

創建子線程並啓動,並在子線程結束時,調用countDown()進行計數器更新

 es1.execute(new Runnable() {
            @Override
            public void run() {
                Thread.sleep(3000);
                System.out.println("子線程:" + Thread.currentThread().getName() + "執行");
                // 核心方法
                latch.countDown();
            }
        });

主線程進行等待

latch.await();

該方法同時提供了一個重載方法,可以設置阻塞的時間,如果超時,直接執行,跳過阻塞。

public boolean await(long timeout, TimeUnit unit)

CyclicBarrier比對

  • CountDownLatch執行一次,完成之後就結束了。
  • CyclicBarrier可以使用多次。比如有4個線程,每個線程內部都分爲3個子任務,而每個線程都需要保持子任務的同步,即4個線程都執行完自己的第一個任務之後,纔開始往下執行第二個任務。

例如

 @Override
        public void run() {
            try {
                Thread.sleep(1000);
                System.out.println(getName() + " 任務1");
                barrier.await();
                
                System.out.println(getName() + " 任務2");
                Thread.sleep(1500);
                barrier.await();
                
                Thread.sleep(2000);
                System.out.println(getName() + " 任務3");
                barrier.await();
                
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

多個run會先打印完任務1纔開始打印任務2

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