CountDownLatch的原理
来源:互联网 发布:nginx tomcat 宕机 编辑:程序博客网 时间:2024/06/13 21:21
今天在学习ZooKeeper的实例的时候,发现了CountDownLatch这个类,那么这个类又是如何使用的呢?以及这个类的原理是什么?我们首先看一下简单的demo:
public class CountDownLatchTest { static class Student implements Runnable { CountDownLatch countDownLatch = null; /** * */ public Student(CountDownLatch countDownLatch) { this.countDownLatch = countDownLatch; } /* * (non-Javadoc) * * @see java.lang.Runnable#run() */ @Override public void run() { try { Thread.sleep( 1000 ); System.out.println( "交卷了!" ); countDownLatch.countDown(); } catch (Exception e) { // TODO: handle exception } } } static class Teacher implements Runnable { CountDownLatch countDownLatch = null; /** * */ public Teacher(CountDownLatch countDownLatch) { this.countDownLatch = countDownLatch; } /* * (non-Javadoc) * * @see java.lang.Runnable#run() */ @Override public void run() { try { countDownLatch.await(); System.out.println( "完成考试了" ); } catch (Exception e) { // TODO: handle exception } } } public static void main(String args[]) { CountDownLatch countDownLatch = new CountDownLatch( 4 ); Executor executor = Executors.newFixedThreadPool( Runtime.getRuntime().availableProcessors() + 1 ); executor.execute( new Student( countDownLatch ) ); executor.execute( new Student( countDownLatch ) ); executor.execute( new Student( countDownLatch ) ); executor.execute( new Student( countDownLatch ) ); executor.execute( new Teacher( countDownLatch ) ); }}
如上面所示,我们首先定义了定义了一个Student的线程,然后在休眠一段时间,执行CountDownLatch.countDown(),然后定义了Teacher的线程,直接等待。CountDownLatch的值降低到0自动会唤醒。
其实CountDownLatch类似于一个计数器,只不过这个计数器同时只有一个线程去操作。
这个类适用于当某个线程等待其他n个线程完成任务的时候再执行相应的任务。
那么CountDownLatch的实现原理是什么呢?我们来看一下源码,当我们初始化CountDownLatch的时候会发生什么事情:
public CountDownLatch(int count) { if (count < 0) throw new IllegalArgumentException("count <0"); this.sync = new Sync(count); }
CountDownLatch在初始化的时候,将内部变量sync进行赋值,sync的变量类型是Sync,那么我们看看Sync的实现
private static final class Sync extends AbstractQueuedSynchronizer { private static final long serialVersionUID = 4982264981922014374L; Sync(int count) { setState(count); } int getCount() { return getState(); } protected int tryAcquireShared(int acquires) { return (getState() == 0) ? 1 : -1; } 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; } } }
我们可以看到Sync也是基于AQS实现的共享锁。那么当调用CountDownLatch.countDown()会发生什么?
public void countDown() { sync.releaseShared(1); }
可以看出来,CountDownLatch.countDown()就是调用AQS的releaseShared(int arg),然后releaseShared(int arg)可以保证将数量原子地减一。
那么CountDownLatch.await()又是如何实现的呢?
public void await() throws InterruptedException { sync.acquireSharedInterruptibly(1); }
await()调用的是sync的acquireSharedInterruptibly(int arg)
public final void acquireSharedInterruptibly(int arg) throws InterruptedException { if (Thread.interrupted()) throw new InterruptedException(); if (tryAcquireShared(arg) < 0) doAcquireSharedInterruptibly(arg); }
在Sync重写了tryAcquireShard(arg),当计数器数字不为0的时候返回-1,因此调用doAcquireShardInterruptibly(arg),而doAcquireShardInterruptibly则会将本线程加载到执行链条的末尾,当别的线程执行完后才会执行,关于AQS的源码解析我们下个文章再看。
- CountDownLatch的原理
- CountDownLatch和CyclicBarrier原理的分析理解
- CountDownLatch实现原理
- CountDownLatch 和 CyclicBarrier 的运用及实现原理
- 深入分析AbstractQueuedSynchronizer共享锁的实现原理:CountDownLatch
- Java并发包中CountDownLatch的工作原理、使用示例
- java CountDownLatch原理和示例
- CountDownLatch的使用方法
- CountDownLatch 的使用
- Java的CountDownLatch
- CountDownLatch 的理解
- CountDownLatch的使用
- countdownlatch的用法
- CountDownLatch的使用方法
- CountDownLatch的用法
- JAVA的CountDownLatch
- Android CountDownLatch的使用
- CountDownLatch的用法
- cocos2d js 调用 c++ 版本cocos2d js 3.6
- 图的广度优先遍历(BFS)
- Swift 2.1 编程语言速览
- 岁月微恙,何惧忧伤
- 一个bat文件执行多个SQL文本
- CountDownLatch的原理
- NSDateFormatter相关整理 -- @ShinePug
- CentOS 7 上systemctl 的用法
- python实现目录树
- codeforces-330-Pasha and Phone(容差定理)
- dota2中的伪随机
- 为开发者准备的9个实用PHP代码片段
- Springmvc的执行流程和mybatis执行流程
- Handler,Looper,Message,MessageQueue,Thread机制的深入理解(举例说明)