java 并发工具包 -倒计数CountDownLatch

来源:互联网 发布:淘宝开学季有什么优惠 编辑:程序博客网 时间:2024/06/10 02:47

简介

CountDownLatch 是一个同步器,翻译过来就是倒计数,意思就是用倒数来计数,当为0的时候结束。

源码分析

public class CountDownLatch {    /**     * 同步器,继承于aqs用来计数     */    private static final class Sync extends AbstractQueuedSynchronizer {        private static final long serialVersionUID = 4982264981922014374L;        //初始化设置状态,即设置初始化计数器        Sync(int count) {            setState(count);        }        //获取state 即获取当前的计数器        int getCount() {            return getState();        }//重写父类方法,尝试判断当前值是否为0          protected int tryAcquireShared(int acquires) {            return (getState() == 0) ? 1 : -1;        }    //重写父类方 尝试判断是否-1是否为0        protected boolean tryReleaseShared(int releases) {            for (;;) {                int c = getState();                if (c == 0)                    return false;                int nextc = c-1;                //cas 替换state值,如果当前不匹配则循环直至state为0或者匹配成功                if (compareAndSetState(c, nextc))                    return nextc == 0;            }        }    }    private final Sync sync;   //初始化  其实就是去初始化sync    public CountDownLatch(int count) {        if (count < 0) throw new IllegalArgumentException("count < 0");        this.sync = new Sync(count);    }    public void await() throws InterruptedException {    //如果计数器还大于0则阻塞当前线程  直到计数器=0为止        sync.acquireSharedInterruptibly(1);    }    //要么一直阻塞到时间过期,要么计数器=0    public boolean await(long timeout, TimeUnit unit)        throws InterruptedException {        return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));    }      //计数器-1  如果-1后=0 则释放线程    public void countDown() {        sync.releaseShared(1);    }        //获取当前计数器    public long getCount() {        return sync.getCount();    }    public String toString() {        return super.toString() + "[Count = " + sync.getCount() + "]";    }}

CountDownLatch源码之所以简单得易于AbstractQueuedSynchronizer 同步器,基本上所有的操作都是由AbstractQueuedSynchronizer 处理

简单例子

public class CountDownLatchTest {    public static void main(String[] args) throws InterruptedException {        CountDownLatch countDownLatch = new CountDownLatch(2);        new Thread(new Runnable() {            @Override            public void run() {                try {                    countDownLatch.await();                    System.out.println("释放线程1");                } catch (InterruptedException e) {                    e.printStackTrace();                }            }        }).start();        new Thread(new Runnable() {            @Override            public void run() {                try {                    countDownLatch.await();                    System.out.println("释放线程2");                } catch (InterruptedException e) {                    // TODO Auto-generated catch block                    e.printStackTrace();                }            }        }).start();        new Thread(new Runnable() {            @Override            public void run() {                System.out.println("计数器-1");                countDownLatch.countDown();            }        }).start();        new Thread(new Runnable() {            @Override            public void run() {                System.out.println("计数器-1");                countDownLatch.countDown();            }        }).start();    }}

总结:

我们前面讲到CyclicBarrier同步器,两者功能类似,都是倒计数,当为0时,释放阻塞线程,但是CyclicBarrier针对的是主线程或者说一个线程,CountDownLatch针对的一组线程(上面例子中有两个线程);
CyclicBarrier可以接收Runnable参数,CountDownLatch不能;
CyclicBarrier通过执行await-1并且一直阻塞直到0大家一起接着执行,CountDownLatch通过countDown,不会阻塞;
这么说吧
CyclicBarrier :主线程和子线程最后会同时执行(如果await后面没有业务处理,和 CountDownLatch效果也类似)
CountDownLatch:一般子线程不管主线程,自己先执行掉

原创粉丝点击