paulwong

          CountDownLatch、CyclicBarrier和Semaphore

          CountDownLatch、CyclicBarrier和Semaphore這三個并發輔助類,可以在線程中呼叫,使得線程暫停等,但各有不同。

          • CountDownLatch
          1、初始化,并傳入計數器
          2、向不同的線程傳入CountDownLatch實例
          3、如果在某一線程中呼叫await(),則此線程被掛起,直到計數器為0,才往下執行
          4、如果在某一線程中呼叫countDown(),計數器減1
          5、最終如果計數器值為0時,則CountDownLatch實例不再起作用了,即為一次性的

          • CyclicBarrier
          1、初始化,并傳入計數器值,也可傳入一個Runnable類,會在計數器為0時,被執行
          2、向不同的線程傳入CyclicBarrier實例
          3、如果在某一線程中呼叫await(),則此線程被掛起,直到計數器為0,才往下執行
          4、其他線程呼叫await(),則此線程被掛起,直到計數器為0,才往下執行
          5、最終如果計數器值為0時,則CyclicBarrier實例會將計數器值恢復,又可重用

          • Semaphore
          1、初始化,并傳入計數器值
          2、向不同的線程傳入Semaphore實例
          3、如果在某一線程中呼叫acquire(),則Semaphore實例會將計數器值減1,如果計數器值為-1,則將計數器值置為0,此線程被掛起,直到計數器值大于1時,才往下執行
          4、此線程需呼叫release(),使得計數器值+1,以便其他線程在計數器值為0時不受阻


          CountDownLatch 例子:
          public class Test {
               public static void main(String[] args) {   
                   final CountDownLatch latch = new CountDownLatch(2);
                    
                   new Thread(){
                       public void run() {
                           try {
                               System.out.println("子線程"+Thread.currentThread().getName()+"正在執行");
                              Thread.sleep(3000);
                              System.out.println("子線程"+Thread.currentThread().getName()+"執行完畢");
                              latch.countDown();
                          } catch (InterruptedException e) {
                              e.printStackTrace();
                          }
                       };
                   }.start();
                    
                   new Thread(){
                       public void run() {
                           try {
                               System.out.println("子線程"+Thread.currentThread().getName()+"正在執行");
                               Thread.sleep(3000);
                               System.out.println("子線程"+Thread.currentThread().getName()+"執行完畢");
                               latch.countDown();
                          } catch (InterruptedException e) {
                              e.printStackTrace();
                          }
                       };
                   }.start();
                    
                   try {
                       System.out.println("等待2個子線程執行完畢");
                      latch.await();
                      System.out.println("2個子線程已經執行完畢");
                      System.out.println("繼續執行主線程");
                  } catch (InterruptedException e) {
                      e.printStackTrace();
                  }
               }
          }

          結果:
          線程Thread-0正在執行
          線程Thread-1正在執行
          等待2個子線程執行完畢
          線程Thread-0執行完畢
          線程Thread-1執行完畢
          2個子線程已經執行完畢
          繼續執行主線程


          CyclicBarrier例子:
          public class Test {
              public static void main(String[] args) {
                  int N = 4;
                  CyclicBarrier barrier  = new CyclicBarrier(N,new Runnable() {
                      @Override
                      public void run() {
                          System.out.println("當前線程"+Thread.currentThread().getName());   
                      }
                  });
                   
                  for(int i=0;i<N;i++)
                      new Writer(barrier).start();
              }
              static class Writer extends Thread{
                  private CyclicBarrier cyclicBarrier;
                  public Writer(CyclicBarrier cyclicBarrier) {
                      this.cyclicBarrier = cyclicBarrier;
                  }
           
                  @Override
                  public void run() {
                      System.out.println("線程"+Thread.currentThread().getName()+"正在寫入數據");
                      try {
                          Thread.sleep(5000);      //以睡眠來模擬寫入數據操作
                          System.out.println("線程"+Thread.currentThread().getName()+"寫入數據完畢,等待其他線程寫入完畢");
                          cyclicBarrier.await();
                      } catch (InterruptedException e) {
                          e.printStackTrace();
                      }catch(BrokenBarrierException e){
                          e.printStackTrace();
                      }
                      System.out.println("所有線程寫入完畢,繼續處理其他任務");
                  }
              }
          }

          執行結果:
          線程Thread-0正在寫入數據
          線程Thread-1正在寫入數據
          線程Thread-2正在寫入數據
          線程Thread-3正在寫入數據
          線程Thread-0寫入數據完畢,等待其他線程寫入完畢
          線程Thread-1寫入數據完畢,等待其他線程寫入完畢
          線程Thread-2寫入數據完畢,等待其他線程寫入完畢
          線程Thread-3寫入數據完畢,等待其他線程寫入完畢
          當前線程Thread-3
          所有線程寫入完畢,繼續處理其他任務
          所有線程寫入完畢,繼續處理其他任務
          所有線程寫入完畢,繼續處理其他任務
          所有線程寫入完畢,繼續處理其他任務


          Semaphore例子:
          public class Test {
              public static void main(String[] args) {
                  int N = 8;            //工人數
                  Semaphore semaphore = new Semaphore(5); //機器數目
                  for(int i=0;i<N;i++)
                      new Worker(i,semaphore).start();
              }
               
              static class Worker extends Thread{
                  private int num;
                  private Semaphore semaphore;
                  public Worker(int num,Semaphore semaphore){
                      this.num = num;
                      this.semaphore = semaphore;
                  }
                   
                  @Override
                  public void run() {
                      try {
                          semaphore.acquire();
                          System.out.println("工人"+this.num+"占用一個機器在生產");
                          Thread.sleep(2000);
                          System.out.println("工人"+this.num+"釋放出機器");
                          semaphore.release();           
                      } catch (InterruptedException e) {
                          e.printStackTrace();
                      }
                  }
              }
          }

          執行結果:
          工人0占用一個機器在生產
          工人1占用一個機器在生產
          工人2占用一個機器在生產
          工人4占用一個機器在生產
          工人5占用一個機器在生產
          工人0釋放出機器
          工人2釋放出機器
          工人3占用一個機器在生產
          工人7占用一個機器在生產
          工人4釋放出機器
          工人5釋放出機器
          工人1釋放出機器
          工人6占用一個機器在生產
          工人3釋放出機器
          工人7釋放出機器
          工人6釋放出機器

          https://www.cnblogs.com/dolphin0520/p/3920397.html

          https://juejin.im/post/5aeec3ebf265da0ba76fa327

          posted on 2019-09-24 10:18 paulwong 閱讀(335) 評論(0)  編輯  收藏 所屬分類: J2SE

          主站蜘蛛池模板: 关岭| 大冶市| 玉树县| 鹤峰县| 庆安县| 石狮市| 绿春县| 宁远县| 阿坝| 磐石市| 南安市| 安阳县| 定远县| 青浦区| 上高县| 东阳市| 永嘉县| 荃湾区| 榆中县| 文登市| 临海市| 中阳县| 平远县| 沛县| 海原县| 宜章县| 南皮县| 新蔡县| 嘉峪关市| 焦作市| 泸西县| 图们市| 上思县| 宜兰县| 西藏| 五台县| 科技| 安新县| 大化| 区。| 都匀市|