zoukankan      html  css  js  c++  java
  • 源码解析-CountDownLatch

    CountDownLatch 作为JUC并发包下一重要工具

    Latch的意思是栅栏,作为一个阀门用来控制多个线程的

    常用方法: new CountDownLatch(参数为放开栅栏的条件);     countDown(); 条件-1           await();  条件未达到0则阻塞住,达到0则放开栅栏 

    两个简单的应用场景

    场景一   五个线程必须都执行完,才能继续往下,任一个线程没执行完都会await()处阻塞住

    场景二   countDownLatch02.await()阻塞在每个线程内部 保证了每个线程都初始化完成,在同一起跑线进行下一步。countDownLatch01的作用同上

    源码分析

     

    老套路了,CountDownLatch下定义了一个内部类Sync 继承自AQS

    so 还是AQS思想 

    大体思想就是:new CountDownLatch(n)  AQS的state设置为n

    每次CountDown() state-1    线程await()时判断state是否为0,如果不为0就加入到AQS的队列,然后将线程挂起。当state==0时 将线程从队列中一个一个唤醒

    OK 到这里就可以结束了,下边是具体源码分析。

    1.  new CountDownLautch(参数)  如上所述 没啥好说的

     

     

    2.  await()方法  

    acquiresharedInterruptibly(参数传1)  参数并没什么意义

    如果当前state不为0,栅栏没有满足打开的条件,则将线程加入队列并挂起

    3.  tryAcquireShared() 用来判断当前state是否为0  

     4. doAcquireSharedInterruptibly()     将线程封装成节点,加入到队列,然后挂起等待唤醒或中断

    将线程封装成节点,加入到队列;           //可以参考https://www.cnblogs.com/ttaall/p/13828134.html 这篇中的addWaiter()部分

    boolean failed = true;

    try {

       for(死循环) {

          获取当前节点的前置节点p;

          if(如果前置节点是头节点) {
            判断当前是否state==0;

            如果栅栏可以打开{

              唤醒头节点并传播下去;

              failed = false;

              return;  //一切顺利并返回

            }

          }

          if (线程是否应该挂起 并挂起 ){

            shouldParkAfterFailedAcquire()  //线程是否应该挂起
            parkAndCheckInterrupt()    //线程挂起,如果被中断则返回true

            抛中断异常

          }

        }

    }finally {

      if (如果中途被中断了){

        解散节点,不玩了

      }

    }

    5. setHeadAndPropagate() 

     Node h  用来保存头节点

    将当前节点设置为头节点;

    if (满足条件){

      Node s = 当前节点的下一个节点;

      if (s是Null  ||  s的下一个节点需要唤醒){

        持续唤醒()

      }

    }

  • 相关阅读:
    iOS UI基础05
    iOS UI基础04
    document.referrer
    节点
    特殊符号编码
    margin和padding的百分比
    XSS要点总结
    页面加载的过程
    函数声明和函数表达式
    jpg和png
  • 原文地址:https://www.cnblogs.com/ttaall/p/13936847.html
Copyright © 2011-2022 走看看