激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術(shù)|正則表達(dá)式|C/C++|IOS|C#|Swift|Android|VB|R語(yǔ)言|JavaScript|易語(yǔ)言|vb.net|

服務(wù)器之家 - 編程語(yǔ)言 - Java教程 - java并發(fā)學(xué)習(xí)-CountDownLatch實(shí)現(xiàn)原理全面講解

java并發(fā)學(xué)習(xí)-CountDownLatch實(shí)現(xiàn)原理全面講解

2021-08-09 10:26康斌825 Java教程

這篇文章主要介紹了java并發(fā)學(xué)習(xí)-CountDownLatch實(shí)現(xiàn)原理全面講解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧

CountDownLatch在多線程并發(fā)編程中充當(dāng)一個(gè)計(jì)時(shí)器的功能,并且維護(hù)一個(gè)count的變量,并且其操作都是原子操作。

如下圖,內(nèi)部有下static final的Sync類繼承自AQS.

java并發(fā)學(xué)習(xí)-CountDownLatch實(shí)現(xiàn)原理全面講解

該類主要通過(guò)countDown()和await()兩個(gè)方法實(shí)現(xiàn)功能的,首先通過(guò)建立CountDownLatch對(duì)象,并且傳入?yún)?shù)即為count初始值。

如果一個(gè)線程調(diào)用了await()方法,那么這個(gè)線程便進(jìn)入阻塞狀態(tài),并進(jìn)入阻塞隊(duì)列。

如果一個(gè)線程調(diào)用了countDown()方法,則會(huì)使count-1;當(dāng)count的值為0時(shí),這時(shí)候阻塞隊(duì)列中調(diào)用await()方法的線程便會(huì)逐個(gè)被喚醒,從而進(jìn)入后續(xù)的操作。

java并發(fā)學(xué)習(xí)-CountDownLatch實(shí)現(xiàn)原理全面講解

補(bǔ)充:Java并發(fā)包中CountDownLatch的工作原理、使用示例

1. CountDownLatch的介紹

CountDownLatch是一個(gè)同步工具,它主要用線程執(zhí)行之間的協(xié)作。CountDownLatch 的作用和 Thread.join() 方法類似,讓一些線程阻塞直到另一些線程完成一系列操作后才被喚醒。在直接創(chuàng)建線程的年代(Java 5.0 之前),我們可以使用 Thread.join()。在線程池出現(xiàn)后,因?yàn)榫€程池中的線程不能直接被引用,所以就必須使用 CountDownLatch 了。

CountDownLatch主要有兩個(gè)方法,當(dāng)一個(gè)或多個(gè)線程調(diào)用await方法時(shí),這些線程會(huì)阻塞。其它線程調(diào)用countDown方法會(huì)將計(jì)數(shù)器減1(調(diào)用countDown方法的線程不會(huì)阻塞),當(dāng)計(jì)數(shù)器的值變?yōu)?時(shí),因await方法阻塞的線程會(huì)被喚醒,繼續(xù)執(zhí)行。

實(shí)現(xiàn)原理:計(jì)數(shù)器的值由構(gòu)造函數(shù)傳入,并用它初始化AQS的state值。當(dāng)線程調(diào)用await方法時(shí)會(huì)檢查state的值是否為0,如果是就直接返回(即不會(huì)阻塞);如果不是,將表示該節(jié)點(diǎn)的線程入列,然后將自身阻塞。當(dāng)其它線程調(diào)用countDown方法會(huì)將計(jì)數(shù)器減1,然后判斷計(jì)數(shù)器的值是否為0,當(dāng)它為0時(shí),會(huì)喚醒隊(duì)列中的第一個(gè)節(jié)點(diǎn),由于CountDownLatch使用了AQS的共享模式,所以第一個(gè)節(jié)點(diǎn)被喚醒后又會(huì)喚醒第二個(gè)節(jié)點(diǎn),以此類推,使得所有因await方法阻塞的線程都能被喚醒而繼續(xù)執(zhí)行。

從源代碼和實(shí)現(xiàn)原理中可以看出一個(gè)CountDownLatch對(duì)象,只能使用一次,不能重復(fù)使用。

await方法源碼

  1. public void await() throws InterruptedException { 
  2. sync.acquireSharedInterruptibly(1); 
  3.   
  4. public final void acquireSharedInterruptibly(int arg) 
  5. throws InterruptedException { 
  6. if (Thread.interrupted()) 
  7. throw new InterruptedException(); 
  8. if (tryAcquireShared(arg) < 0) 
  9. doAcquireSharedInterruptibly(arg); 
  10.   
  11. protected int tryAcquireShared(int acquires) { 
  12. return (getState() == 0) ? 1 : -1; 

doAcquireSharedInterruptibly 主要實(shí)現(xiàn)線程的入列與阻塞。

countDown方法

  1. public void countDown() {
  2. sync.releaseShared(1);
  3. }
  4.  
  5. public final boolean releaseShared(int arg) {
  6. if (tryReleaseShared(arg)) {
  7. doReleaseShared();
  8. return true;
  9. }
  10. return false;
  11. }
  12.  
  13. protected boolean tryReleaseShared(int releases) {
  14. // Decrement count; signal when transition to zero
  15. for (;;) {
  16. int c = getState();
  17. if (c == 0)
  18. return false;
  19. int nextc = c-1;
  20. if (compareAndSetState(c, nextc))
  21. return nextc == 0;
  22. }
  23. }

doReleaseShared主要實(shí)現(xiàn)喚醒第一個(gè)節(jié)點(diǎn),第一個(gè)節(jié)點(diǎn)有會(huì)喚醒第二個(gè)節(jié)點(diǎn),……。

2. 使用示例

  1. package demo;
  2. import java.util.Random;
  3. import java.util.concurrent.CountDownLatch;
  4. import java.util.concurrent.ExecutorService;
  5. import java.util.concurrent.Executors;
  6. public class CountDownLatchDemo {
  7. private CountDownLatch cdl = new CountDownLatch(2);
  8. private Random rnd = new Random();
  9.  
  10. class FirstTask implements Runnable{
  11. private String id;
  12.  
  13. public FirstTask(String id){
  14. this.id = id;
  15. }
  16.  
  17. @Override
  18. public void run(){
  19. System.out.println("Thread "+ id + " is start");
  20. try {
  21. Thread.sleep(rnd.nextInt(1000));
  22. } catch (InterruptedException e) {
  23. e.printStackTrace();
  24. }
  25. System.out.println("Thread "+ id + " is over");
  26. cdl.countDown();
  27. }
  28. }
  29.  
  30. class SecondTask implements Runnable{
  31. private String id;
  32.  
  33. public SecondTask(String id){
  34. this.id = id;
  35. }
  36.  
  37. @Override
  38. public void run(){
  39. try {
  40. cdl.await();
  41. } catch (InterruptedException e) {
  42. e.printStackTrace();
  43. }
  44. System.out.println("----------Thread "+ id + " is start");
  45. try {
  46. Thread.sleep(rnd.nextInt(1000));
  47. } catch (InterruptedException e) {
  48. e.printStackTrace();
  49. }
  50. System.out.println("----------Thread "+ id + " is over");
  51. }
  52. }
  53.  
  54. public static void main(String[] args){
  55. ExecutorService es = Executors.newCachedThreadPool();
  56. CountDownLatchDemo cdld = new CountDownLatchDemo();
  57. es.submit(cdld.new SecondTask("c"));
  58. es.submit(cdld.new SecondTask("d"));
  59. es.submit(cdld.new FirstTask("a"));
  60. es.submit(cdld.new FirstTask("b"));
  61. es.shutdown();
  62. }
  63. }

在這個(gè)示例中,我們創(chuàng)建了四個(gè)線程a、b、c、d,這四個(gè)線程幾乎同時(shí)提交給了線程池。c線程和d線程會(huì)在a線程和b線程結(jié)束后開始執(zhí)行。

運(yùn)行結(jié)果

  1. Thread a is start
  2. Thread b is start
  3. Thread b is over
  4. Thread a is over
  5. ----------Thread c is start
  6. ----------Thread d is start
  7. ----------Thread d is over
  8. ----------Thread c is over

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持服務(wù)器之家。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教。

原文鏈接:https://blog.csdn.net/kangbin825/article/details/105397247

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 精品三区视频 | 黄色成年在线观看 | 国产一级毛片国语版 | www.精品久久 | 神马视频我不卡 | 亚洲白嫩在线观看 | 日本一区二区免费在线播放 | 国产精品区一区二区三区 | av在线免费看网站 | 一区二区三区黄色 | 奇米影视亚洲春色 | 亚洲资源在线 | 成人国产精品一区二区毛片在线 | 91精品影视 | 偿还电影免费看 | 亚洲国产精品高潮呻吟久久 | 黄污污网站 | 日韩精品中文字幕在线播放 | 久草视频福利在线观看 | 毛片午夜| 久久精品视频免费观看 | 91久久一区 | 国产成人高清在线观看 | 看免费5xxaaa毛片 | 久久密| 国产三级影院 | 免费午夜视频在线观看 | 欧美三级欧美成人高清www | 羞羞草视频 | www.48xx.com| 一区二区三视频 | 国产精品jk白丝蜜臀av软件 | 欧美a在线 | 黑人一区二区三区四区五区 | 精品国产一区二区三区天美传媒 | 国产精品一品二区三区四区18 | 无遮挡一级毛片视频 | 欧美成人精品一区二区三区 | 色交视频 | xvideos korean| 免费看成年人网站 |