3.13 CountDownLatch使用及原理

3.13 CountDownLatch

 * <p>A {
     @code CountDownLatch} is initialized with a given <em>count</em>.
 * The {
     @link #await await} methods block until the current count reaches
 * zero due to invocations of the {
     @link #countDown} method, after which
 * all waiting threads are released and any subsequent invocations of
 * {
     @link #await await} return immediately.zhe  This is a one-shot phenomenon
 * -- the count cannot be reset.  If you need a version that resets the
 * count, consider using a {
     @link CyclicBarrier}.

       通过一个指定数量即可构建CountDownLatch实例,该实例的await方法可以阻塞当前线程知道其他线程使用该实例的countDown方法使count值减至0,减少至0后所有等待的线程都会立即释放,这是只有一次的操作,因为CountDownLatch的count值只能设置一次,如果一个重新设置count值带版本号,请使用CyclicBarrier。


3.13.1 CountDownLatch使用方法

       1. 通过带传入一个count值构造一个CountDownLatch。

CountDownLatch latch = new CountDownLatch(5);

       使用await方法可以阻塞当前线程。

latch.await();

       使用countDown方法可以减少count值,直到该值减至0,所有阻塞的线程将立即释放。

latch.countDown();

       完整demo。

public static void main(String[] args) throws InterruptedException {
     
	//创建
    CountDownLatch latch = new CountDownLatch(5);
    new Thread(()->{
     
        try {
     
        	//第一个线程被阻塞
            latch.await();
        } catch (InterruptedException e) {
     
            e.printStackTrace();
        }
        System.err.println("其他线程等待");
    }).start();
    for (int i=0;i<10;i++){
     
        Thread.sleep(2000);
        new Thread(()->{
     
        	//其他线程执行countDown(),当count值减少到0,上边等待的线程将被释放
            System.out.println(Thread.currentThread().getName());
            latch.countDown();
        }).start();
    }

}

3.13 CountDownLatch使用及原理_第1张图片
       由上述例子可以看出,通过CountDownLatch可以实现线程见通信,完成线程执行的先后逻辑。可以实现某线程在其他线程工作完成后再继续运行的功能。


3.13.2 CountDownLatch源码

       其内部由一个Sync组成,其count值Sync这个里面维护着。

private final Sync sync;

       再来看看Sync是什么?

/**
 * Synchronization control For CountDownLatch.
 * Uses AQS state to represent count.
 * AbstractQueuedSynchronizer即表示AQS,内部维护了一个正在执行线程和等待线程之间的关系。
 */
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;
        }
    }
}

       使用CountDownLatch时会先将count值传入进行构造,该count值再sync里,sync会调用setState(count)方法将该值给sync的state属性。

public CountDownLatch(int count) {
     
    if (count < 0) throw new IllegalArgumentException("count < 0");
    this.sync = new Sync(count);
}
Sync(int count) {
     
    setState(count);
}

       调用countDown()方法。

public void countDown() {
     
    sync.releaseShared(1);
}

       最后countDown()执行的时sync的tryReleaseShared方法逻辑,该releases是1,再getState方法不为0是,会返回一个返回一个c-1,就是原来的state减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;
    }
}

你可能感兴趣的:(#,3,多线程和并发,java,并发编程,CountDownLatch,CountDown原理,多线程)