最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

 更新時間:2021年02月18日 10:36:13   作者:康斌825  
這篇文章主要介紹了java并發(fā)學習-CountDownLatch實現(xiàn)原理全面講解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧

CountDownLatch在多線程并發(fā)編程中充當一個計時器的功能,并且維護一個count的變量,并且其操作都是原子操作。

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

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

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

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

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

1. CountDownLatch的介紹

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

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

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

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

await方法源碼

public void await() throws InterruptedException {
 sync.acquireSharedInterruptibly(1);
}
 
public final void acquireSharedInterruptibly(int arg)
  throws InterruptedException {
 if (Thread.interrupted())
  throw new InterruptedException();
 if (tryAcquireShared(arg) < 0)
  doAcquireSharedInterruptibly(arg);
}
 
protected int tryAcquireShared(int acquires) {
 return (getState() == 0) ? 1 : -1;
}

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

countDown方法

public void countDown() {
 sync.releaseShared(1);
}
 
public final boolean releaseShared(int arg) {
 if (tryReleaseShared(arg)) {
  doReleaseShared();
  return true;
 }
 return false;
}
 
protected boolean tryReleaseShared(int releases) {
 // Decrement count; signal when transition to zero
 for (;;) {
  int c = getState();
  if (c == 0)
   return false;
  int nextc = c-1;
  if (compareAndSetState(c, nextc))
   return nextc == 0;
 }
}

doReleaseShared主要實現(xiàn)喚醒第一個節(jié)點,第一個節(jié)點有會喚醒第二個節(jié)點,……。

2. 使用示例

package demo; 
import java.util.Random;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; 
public class CountDownLatchDemo { 
 private CountDownLatch cdl = new CountDownLatch(2); 
 private Random rnd = new Random();
 
 class FirstTask implements Runnable{
 private String id;
 
 public FirstTask(String id){
 this.id = id;
 }
 
 @Override
 public void run(){
 System.out.println("Thread "+ id + " is start");
 try {
 Thread.sleep(rnd.nextInt(1000));
 } catch (InterruptedException e) {
 e.printStackTrace();
 }
 System.out.println("Thread "+ id + " is over");
 cdl.countDown();
 }
 }
 
 class SecondTask implements Runnable{
 private String id;
 
 public SecondTask(String id){
 this.id = id;
 }
 
 @Override
 public void run(){
 try {
 cdl.await();
 } catch (InterruptedException e) {
 e.printStackTrace();
 }
 System.out.println("----------Thread "+ id + " is start");
 try {
 Thread.sleep(rnd.nextInt(1000));
 } catch (InterruptedException e) {
 e.printStackTrace();
 }
 System.out.println("----------Thread "+ id + " is over");
 }
 }
 
 public static void main(String[] args){
 ExecutorService es = Executors.newCachedThreadPool();
 CountDownLatchDemo cdld = new CountDownLatchDemo();
 es.submit(cdld.new SecondTask("c"));
 es.submit(cdld.new SecondTask("d"));
 es.submit(cdld.new FirstTask("a"));
 es.submit(cdld.new FirstTask("b"));
 es.shutdown();
 } 
}

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

運行結(jié)果

Thread a is start
Thread b is start
Thread b is over
Thread a is over
----------Thread c is start
----------Thread d is start
----------Thread d is over
----------Thread c is over

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。如有錯誤或未考慮完全的地方,望不吝賜教。

相關(guān)文章

最新評論

高清| 碌曲县| 石柱| 钟山县| 区。| 宝应县| 陈巴尔虎旗| 丽水市| 金阳县| 钟山县| 柯坪县| 黎川县| 霍城县| 沛县| 囊谦县| 忻城县| 和顺县| 噶尔县| 油尖旺区| 龙里县| 勃利县| 两当县| 枣阳市| 彰化市| 阿图什市| 育儿| 嘉善县| 乐山市| 乌鲁木齐县| 三亚市| 寿阳县| 准格尔旗| 吉首市| 改则县| 鹤庆县| 库尔勒市| 香港| 大荔县| 昔阳县| 乐都县| 阳新县|