CountDownLatch、CyclicBarrier和Semaphore使用

  • 2019 年 10 月 6 日
  • 筆記
  • CountDownLatch

CountDownLatch是用來執行緒計數的。等待一組執行緒全部執行完後再本執行緒繼續執行。如:A執行緒需要等待B、C和D(由初始化CountDownLatch參數覺得等待多少個執行緒)執行緒執行完後再執行。

主要的方法:

// 構造方法,count決定等待多少個執行緒  public CountDownLatch(int count)  // 等待執行緒完成數減1  public void countDown()  // 調用await本執行緒會掛起,當等待執行緒未完成數為0,即countDown調用次數等於構造方法參數值時會被喚醒  public void await()  public boolean await(long timeout, TimeUnit unit)

以下是CountDownLatch的用法:

public class CountDownLatchTest {      public static void main(String[] args) {          final CountDownLatch countDownLatch = new CountDownLatch(2);          for (int i = 0; i < 2; i++) {              new Thread(() -> {                  try {                      String name = Thread.currentThread().getName();                      System.out.println("子執行緒" + name + "正在運行中......");                      TimeUnit.SECONDS.sleep(5);                      System.out.println("子執行緒" + name + "執行完畢");                      countDownLatch.countDown();                  } catch (Exception e) {                      e.printStackTrace();                  }              }).start();          }            try {              System.out.println("======等待兩個子執行緒執行完畢");              // 只有子執行緒執行完畢個數等於CountDownLatch初始化個數才會繼續執行await後面程式碼              countDownLatch.await();              System.out.println("兩個子執行緒都執行完畢!!!!!!");          } catch (InterruptedException e) {              e.printStackTrace();          }            System.out.println("主執行緒繼續執行中。。。。。。。。");      }  }

結果:

子執行緒Thread-0正在運行中......  ======等待兩個子執行緒執行完畢  子執行緒Thread-1正在運行中......  子執行緒Thread-1執行完畢  子執行緒Thread-0執行完畢  兩個子執行緒都執行完畢!!!!!!  主執行緒繼續執行中。。。。。。。。
  • CyclicBarrier

CyclicBarrier 設置一個障礙點,讓同組執行緒到達改點的執行緒等待本組未達到該點的執行緒,同組全部執行緒到達該點才越過障礙物釋放資源,讓其它組循環利用該對象。

主要方法:

// 構造方法設置同組執行緒數  public CyclicBarrier(int parties)  // 構造方法設置同組執行緒數;全部達到障礙物時執行barrierAction函數  public CyclicBarrier(int parties, Runnable barrierAction)  // 某個執行緒調用await時掛起,需要等同組所有執行緒到達才能喚醒  public int await() throws InterruptedException, BrokenBarrierException

以下是 CyclicBarrier 的用法:

/**   * Created on 18/3/15 14:40.   *   * @author wolf   */  public class CyclicBarrierTest {      public static void main(String[] args) {          int n = 3;          CyclicBarrier barrier = new CyclicBarrier(n);          for (int i = 0; i < 3; i++) {              new Worker(barrier).start();          }            try {              TimeUnit.SECONDS.sleep(6);              System.out.println("--------討厭的循環利用分割線------------");          } catch (Exception e) {              e.printStackTrace();          }            for (int i = 0; i < n; i++) {              new Worker(barrier).start();          }      }        static class Worker extends Thread {          private CyclicBarrier barrier;          public Worker(CyclicBarrier barrier) {              this.barrier = barrier;          }          @Override          public void run() {              long startTime = System.currentTimeMillis();              String name = Thread.currentThread().getName();              System.out.println("執行緒 " + name + " 正在執行任務.......");              try {                  int time = RandomUtils.nextInt(1, 5);                  TimeUnit.SECONDS.sleep(time);                  System.out.println("執行緒 " + name + " 執行任務完畢!!!用時:" + time);                  barrier.await();              } catch (Exception e) {                  e.printStackTrace();              }              System.out.println("執行緒 " + name + " 全部耗時:"+(System.currentTimeMillis()-startTime));          }      }  }
  • Semaphore

Semaphore 通過名字我們就知道這個計算訊號量,也就是控制獲取資源的許可證。

主要的方法:

// 構造方法設置可用資源的數量,即許可證的數量  public Semaphore(int permits)  // 構造方法設置可用資源的數量,即許可證的數量,fair 是否公平獲得許可證,默認是先來後到公平的  public Semaphore(int permits, boolean fair)  // 同步獲取許可證,  public void acquire() throws InterruptedException  // 嘗試獲取許可證,結果直接返回  public boolean tryAcquire()  // 嘗試獲取許可證,結果等待時間超時直接返回  public boolean tryAcquire(long timeout, TimeUnit unit)  // 釋放許可證,可給其它等待執行緒使用  public void release()

以下是 Semaphore 用法:

public class SemaphoreTest {      public static void main(String[] args) {          int no = 5;          Semaphore semaphore = new Semaphore(2);          for (int i = 0; i < no; i++) {              new Worker(i, semaphore).start();          }      }      static class Worker extends Thread {          private int no;          private Semaphore semaphore;          public Worker(int no, Semaphore semaphore) {              this.no = no;              this.semaphore = semaphore;          }          @Override          public void run() {              try {                  long startTime = System.currentTimeMillis();                  semaphore.acquire();                  System.out.println("worker " + this.no + " 獲取許可證,開始工作....");                  int time = RandomUtils.nextInt(1, 5);                  TimeUnit.SECONDS.sleep(time);                  semaphore.release();                  System.out.println("worker " + this.no + " 完成工作,釋放許可證!耗時:" + (System.currentTimeMillis() - startTime));              } catch (Exception e) {                  e.printStackTrace();              }          }      }  }