Skip to content

Latest commit

 

History

History
97 lines (64 loc) · 3.39 KB

countdownlatch.md

File metadata and controls

97 lines (64 loc) · 3.39 KB

CountDownLatch

解释

CountDownLatchjava.util.concurrent包中的一个工具类,用于线程计数。

它提供了一种同步的功能,允许一个或多个线程等待其他一系列在其他线程的操作完成后,继续执行当前线程。

并且,该对象是不可重用的,对象内存储的状态值一旦被减少为“0”,就无法再次重新设置。

入门demo

    public static void main(String[] args) throws InterruptedException {
        int num = 3;	// 创建的线程数量
        CountDownLatch countDownLatch = new CountDownLatch(num);
        for (int i = 0; i < num; i++) {
            new Thread(new Worker(countDownLatch)).start();
        }
        countDownLatch.await(); // 等待所有线程执行完毕,再向下执行
        System.out.println("主线程执行完毕");
    }

    static class Worker implements Runnable {
        private CountDownLatch countDownLatch;
        public Worker(CountDownLatch countDownLatch) {
            this.countDownLatch = countDownLatch;
        }
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName() + "正在执行...");
            countDownLatch.countDown(); // 通知count执行完毕
        }
    }

上面的程序定义了一个num变量用于指定CountDownLatchawait()方法等待的线程数量。

初始化一个CountDownLatch对象,并将该对象传入子线程中。子线程中通过调用CountDownLatchcountDown()方法来通知CountDownLatch当前线程执行完毕,由CountDownLatch对象进行计数。

主线程通过调用CountDownLatchawait()方法等待线程计数等于指定的线程数量。当两者相等时,唤醒主线程继续执行。

程序输出如下:

Thread-1正在执行...
Thread-2正在执行...
Thread-0正在执行...
主线程执行完毕

源码解析

原理

CountDownLatch通过使用线程锁的方式,对线程进行计数。

内部锁

private static final class Sync extends AbstractQueuedSynchronizer {}

上述对象是CountDownLatch内部的锁实现类。

该类中通过设置父类的state状态值变量,并重写tryAcquireSharedtryReleaseShared对此状态进行修改。tryAcquireShared方法通过检查状态值是否为0尝试获取共享锁,tryReleaseShared释放锁的同时修改状态值,释放成功后对状态值进行-1操作。

构造器

public CountDownLatch(int count) {}

CountDownLatch仅提供了上面一个构造器,用于指定监听计数的线程数量。

await()

public void await() throws InterruptedException {}
public boolean await(long timeout, TimeUnit unit)
        throws InterruptedException {}

该方法用于获取共享锁,内部通过调用Sync对象的tryAcquireShared获取锁,但是该方法会检测锁的状态值,只有状态值为0,也就是所有的监听线程都执行完毕后,锁才能正常获取到,否则,调用该方法的线程进行阻塞。

countDown()

public void countDown() {}

countDown()方法通过释放锁的操作来修改状态值,每调用一次,状态值就减少1,知道状态值减少为0时,通知调用await()方法的线程再次进行锁获取操作。