国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > Java > 正文

java多線程學(xué)習(xí)-java.util.concurrent詳解(一) Latch/Barrier

2019-11-11 07:05:02
字體:
供稿:網(wǎng)友

java.util.concurrent, 提供了大量高級工具,可以幫助開發(fā)者編寫高效、易維護(hù)、結(jié)構(gòu)清晰的Java多線程程序

1. CountDownLatch     我們先來學(xué)習(xí)一下JDK1.5 API中關(guān)于這個類的詳細(xì)介紹: “一個同步輔助類,在完成一組正在其他線程中執(zhí)行的操作之前,它允許一個或多個線程一直等待。 用給定的計數(shù) 初始化 CountDownLatch。由于調(diào)用了 countDown() 方法,所以在當(dāng)前計數(shù)到達(dá)零之前,await 方法會一直受阻塞。之后,會釋放所有等待的線程,await 的所有后續(xù)調(diào)用都將立即返回。這種現(xiàn)象只出現(xiàn)一次——計數(shù)無法被重置。如果需要重置計數(shù),請考慮使用 CyclicBarrier。”     這就是說,CountDownLatch可以用來管理一組相關(guān)的線程執(zhí)行,只需在主線程中調(diào)用CountDownLatch 的await方法(一直阻塞),讓各個線程調(diào)用countDown方法。當(dāng)所有的線程都只需完countDown了,await也順利返回,不再阻塞了。在這樣情況下尤其適用:將一個任務(wù)分成若干線程執(zhí)行,等到所有線程執(zhí)行完,再進(jìn)行匯總處理。     下面我舉一個非常簡單的例子。假設(shè)我們要打印1-100,最后再輸出“Ok“。1-100的打印順序不要求統(tǒng)一,只需保證“Ok“是在最后出現(xiàn)即可。     解決方案:我們定義一個CountDownLatch,然后開10個線程分別打印(n-1)*10+1至(n-1)*10+10。主線程中調(diào)用await方法等待所有線程的執(zhí)行完畢,每個線程執(zhí)行完畢后都調(diào)用countDown方法。最后再await返回后打印“Ok”。 具體代碼如下(本代碼參考了JDK示例代碼):

import java.util.concurrent.CountDownLatch;  /**  * 示例:CountDownLatch的使用舉例  * Mail: ken@iamcoding.com  * @author janeky  */  public class TestCountDownLatch {      PRivate static final int N = 10;        public static void main(String[] args) throws InterruptedException {          CountDownLatch doneSignal = new CountDownLatch(N);          CountDownLatch startSignal = new CountDownLatch(1);//開始執(zhí)行信號            for (int i = 1; i <= N; i++) {              new Thread(new Worker(i, doneSignal, startSignal)).start();//線程啟動了          }          System.out.println("begin------------");          startSignal.countDown();//開始執(zhí)行啦          doneSignal.await();//等待所有的線程執(zhí)行完畢          System.out.println("Ok");        }        static class Worker implements Runnable {          private final CountDownLatch doneSignal;          private final CountDownLatch startSignal;          private int beginIndex;            Worker(int beginIndex, CountDownLatch doneSignal,                  CountDownLatch startSignal) {              this.startSignal = startSignal;              this.beginIndex = beginIndex;              this.doneSignal = doneSignal;          }            public void run() {              try {                  startSignal.await(); //等待開始執(zhí)行信號的發(fā)布                  beginIndex = (beginIndex - 1) * 10 + 1;                  for (int i = beginIndex; i <= beginIndex + 10; i++) {                      System.out.println(i);                  }              } catch (InterruptedException e) {                  e.printStackTrace();              } finally {                  doneSignal.countDown();              }          }      }  }  

總結(jié):CounDownLatch對于管理一組相關(guān)線程非常有用。上述示例代碼中就形象地描述了兩種使用情況。第一種是計算器為1,代表了兩種狀態(tài),開關(guān)。第二種是計數(shù)器為N,代表等待N個操作完成。今后我們在編寫多線程程序時,可以使用這個構(gòu)件來管理一組獨立線程的執(zhí)行。 

2. CyclicBarrier     我們先來學(xué)習(xí)一下JDK1.5 API中關(guān)于這個類的詳細(xì)介紹:     “一個同步輔助類,它允許一組線程互相等待,直到到達(dá)某個公共屏障點 (common barrier point)。在涉及一組固定大小的線程的程序中,這些線程必須不時地互相等待,此時 CyclicBarrier 很有用。因為該 barrier 在釋放等待線程后可以重用,所以稱它為循環(huán) 的 barrier。     CyclicBarrier 支持一個可選的 Runnable 命令,在一組線程中的最后一個線程到達(dá)之后(但在釋放所有線程之前),該命令只在每個屏障點運行一次。若在繼續(xù)所有參與線程之前更新共享狀態(tài),此屏障操作 很有用。     我們在學(xué)習(xí)CountDownLatch的時候就提到了CyclicBarrier。兩者究竟有什么聯(lián)系呢?引用[JCip]中的描述“The key difference is that with a barrier, all the threads must come together at a barrier point at the same time in order to proceed. Latches are for waiting for events; barriers are for waiting for other threads。CyclicBarrier等待所有的線程一起完成后再執(zhí)行某個動作。這個功能CountDownLatch也同樣可以實現(xiàn)。但是CountDownLatch更多時候是在等待某個事件的發(fā)生。在CyclicBarrier中,所有的線程調(diào)用await方法,等待其他線程都執(zhí)行完。     舉一個很簡單的例子,今天晚上我們哥們4個去Happy。就互相通知了一下:晚上八點準(zhǔn)時到xx酒吧門前集合,不見不散!。有個哥們住的近,早早就到了。有的事務(wù)繁忙,剛好踩點到了。無論怎樣,先來的都不能獨自行動,只能等待所有人 代碼如下(參考了網(wǎng)上給的一些教程) 

import java.util.Random;  import java.util.concurrent.BrokenBarrierException;  import java.util.concurrent.CyclicBarrier;  import java.util.concurrent.ExecutorService;  import java.util.concurrent.Executors;    public class TestCyclicBarrier {        public static void main(String[] args) {                ExecutorService exec = Executors.newCachedThreadPool();               final Random random=new Random();                    final CyclicBarrier barrier=new CyclicBarrier(4,new Runnable(){              @Override              public void run() {                  System.out.println("大家都到齊了,開始happy去");              }});                    for(int i=0;i<4;i++){              exec.execute(new Runnable(){                  @Override                  public void run() {                      try {                          Thread.sleep(random.nextInt(1000));                      } catch (InterruptedException e) {                          e.printStackTrace();                      }                      System.out.println(Thread.currentThread().getName()+"到了,其他哥們呢");                      try {                          barrier.await();//等待其他哥們                      } catch (InterruptedException e) {                          e.printStackTrace();                      } catch (BrokenBarrierException e) {                          e.printStackTrace();                      }                  }});          }          exec.shutdown();      }    }  

關(guān)于await方法要特別注意一下,它有可能在阻塞的過程中由于某些原因被中斷 總結(jié):CyclicBarrier就是一個柵欄,等待所有線程到達(dá)后再執(zhí)行相關(guān)的操作。barrier 在釋放等待線程后可以重用。 


發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 济阳县| 乌兰浩特市| 石楼县| 内江市| 岳阳市| 邵阳市| 丰原市| 南雄市| 尤溪县| 修武县| 南昌县| 时尚| 思南县| 洛隆县| 庄河市| 神木县| 上饶县| 嘉禾县| 山阳县| 都匀市| 延川县| 玉树县| 喀什市| 广州市| 太白县| 镇安县| 南昌市| 青龙| 夹江县| 林口县| 绥滨县| 建阳市| 虹口区| 荣成市| 普洱| 鄂托克前旗| 抚顺县| 客服| 沙田区| 措勤县| 九龙县|