CountDownLatch

CountDownLatch是闭锁的一种实现;CountDownLatch是在java1.5被引入;

CountDownLatch这个类能够使一个线程等待其他线程完成各自的工作后再执行;

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

主要API:

  • countDown():该方法递减计数器,表示有一个事件已经发生;
  • await():该方法等待计时器达到零,达到零后表示需要等待的所有事件都已发生;

如果计数器的值非零,await方法会一直阻塞直到计数器为零,或者等待中的线程中断,或者等待超时;

起始门(Starting Gate)

所有子线程等待计数器为零后一起执行

public class Appliction {
    private final static int NUM = 10;

    public static void main(String[] args) {
        CountDownLatch countDownLatch = new CountDownLatch(1);
        for (int i = 0; i < NUM; i++) {
            new Thread(() -> {
                try {
                    countDownLatch.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.err.println(Thread.currentThread().getName() + " started:" + System.currentTimeMillis());
            }).start();
        }
        countDownLatch.countDown();
        System.err.println("main thread exec end");
    }
}
结束门(Ending Gate)

等待所有子任务或子线程结束后(计数器为零),对执行结果进行统计或汇总

/**
 * 假设有10块磁盘,需要10个线程同时统计磁盘空间大小,统计完成后由主线程进行汇总
 */
public class Appliction {
    private final static int NUM = 10;

    public static void main(String[] args) throws InterruptedException {
        CountDownLatch countDownLatch = new CountDownLatch(NUM);
        List<Disk> tasks = new ArrayList<>(NUM);
        for (int i = 0; i < NUM; i++) {
            tasks.add(new Disk());
        }
        for (Disk dk : tasks) {
            new Thread(new DiskCountTask(countDownLatch, dk)).start();
        }
        countDownLatch.await();
        int size = tasks.stream().mapToInt(Disk::getSize).sum();
        System.err.println("All disk space size:" + size);
    }


}

class Disk {
    private Integer size;

    public Integer getSize() {
        return size;
    }

    public void setSize(Integer size) {
        this.size = size;
    }
}

class DiskCountTask implements Runnable {
    private Disk disk;
    private CountDownLatch downLatch;

    public DiskCountTask(CountDownLatch downLatch, Disk disk) {
        this.downLatch = downLatch;
        this.disk = disk;
    }

    @Override
    public void run() {
        int size = new Random().nextInt(10);
        try {
            TimeUnit.SECONDS.sleep(size);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        disk.setSize(size);
        System.err.println(Thread.currentThread().getName() + " exec end[" + System.currentTimeMillis() + "], size:" + size);
        downLatch.countDown();
    }
}

设想有这样一个功能需要Thread1、Thread2、Thread3、Thread4四条线程分别统计C、D、E、F四个盘的大小,所有线程都统计完毕交给主线程去做汇总,利用CountDownLatch来完成就非常轻松

results matching ""

    No results matching ""