Java并发--CountDownLatch类

CountDownLatch

CountDownLatch是一个同步辅助类,位于java.util.concurrent包中。

其作用是:在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。

闭锁可以延迟线程的进度知道其达到终止状态,闭锁可以用来确保某些活动直到其他活动都完成才继续执行:

  • 确保某个计算在其需要的所有资源都被初始化之后才继续执行;
  • 确保某个服务在其依赖的所有其他服务都已经启动之后才启动;
  • 等待直到某个操作所有参与者都准备就绪再继续执行;

CountDownLatch的构造函数接收一个int类型的参数作为计数器,如果我们想等待N个点完成,这里就传入N。

当我么调用CountDownLatch的countDown()方法时,N就会减一,CountDownLatch的await方法会阻塞当前线程,知道N变成零。由于CountDown()方法可以用在任何地方,所以这里说的N个点,可以使N个线程,也可以是1个线程里的N个执行步骤。用在多个线程时,只需要把这个CountDownLatch的引用传递到线程里面即可。

是通过一个计数器来实现的,计数器的初始值是线程的数量。每当一个线程执行完毕后,计数器的值就-1,当计数器的值为0时,表示所有线程都执行完毕,然后在闭锁上等待的线程就可以恢复工作了。

注意: 计数器必须大于等于0,只是等于0的时候,计数器就是0,调用await方法时不会阻塞当前线程。CountDownLatch不可能重新初始化或者修改CountDownLatch对象的内部计数器。一个线程调用的countDown()方法happen-before,另外一个线程调用await方法。

源码

该类只提供了一个构造器:

    /**
     * Constructs a {@code CountDownLatch} initialized with the given count.
     *
     * @param count the number of times {@link #countDown} must be invoked
     *        before threads can pass through {@link #await}
     * @throws IllegalArgumentException if {@code count} is negative
     */
    public CountDownLatch(int count) {
        if (count < 0) throw new IllegalArgumentException("count < 0");
        this.sync = new Sync(count);
    }

重要的方法:

/调用await()方法的线程会被挂起,它会等待直到count值为0才继续执行
public void await() throws InterruptedException { };   

//和await()类似,只不过等待一定的时间后count值还没变为0的话就会继续执行
public boolean await(long timeout, TimeUnit unit) throws InterruptedException { };  

//将count值减1
public void countDown() { };  

示例:计算20个线程执行共耗费的时间

package pers.zhang.juc.part1;


import java.util.concurrent.CountDownLatch;

/**
 * @author zhang
 * @date 2020/1/16 - 19:58
 *
 * CountDownLatch:闭锁,在完成某些运算时,只有其他所有线程的运算全部完成,当前运算才继续执行。
 */
public class TestCountDownLatch {
    public static void main(String[] args) {
        final CountDownLatch latch = new CountDownLatch(10);
        LatchDemo ld = new LatchDemo(latch);

        //开始时间
        long startTime = System.currentTimeMillis();
        for(int i = 0; i < 10; i++){
            new Thread(ld).start();
        }

        //主线程等待其他10个线程执行完毕
        try {
            latch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        long endTime = System.currentTimeMillis();
        System.out.println("10个并发线程共耗费时间为:" + (endTime - startTime));
    }
}


class LatchDemo implements Runnable{

    private CountDownLatch latch;

    public LatchDemo(CountDownLatch latch){
        this.latch = latch;
    }

    @Override
    public void run() {
        synchronized (this){
            try {
                for(int i = 0; i < 50000; i++){
                    if(i % 2 == 0){
                        System.out.println(i);
                    }
                }
            }finally {
                latch.countDown();//计数器减一,必须执行
            }
        }
    }
}

在这里插入图片描述

发布了616 篇原创文章 · 获赞 1840 · 访问量 22万+

猜你喜欢

转载自blog.csdn.net/cold___play/article/details/104010351