Java并发CountDownLatch和CyclicBarrier

137 阅读2分钟

文章目录

一.简介

CountDownLatch和CyclicBarrier是jdk concurrent包下工具类,提供一种控制并发流程的工具。

二.CountDownLatch

构造类,常用api

public CountDownLatch(int count) {  };  //参数count为计数值
public void await() throws InterruptedException { };   //调用await()方法的线程会被挂起,它会等待直到count值为0才继续执行
public boolean await(long timeout, TimeUnit unit) throws InterruptedException { };  //和await()类似,只不过等待一定的时间后count值还没变为0的话就会继续执行
public void countDown() { };  //将count值减1

示例

线程池管理线程资源, join() 等待线程执行失效,CountDownLatch处理线程等待。

public class CountDownLatchTest {
    public static void main(String[] args) {
        final CountDownLatch countDownLatch = new CountDownLatch(2);
        Thread t1 = new Thread(()->{
            System.out.println("子线程:"+Thread.currentThread().getName());
            try {
                Thread.sleep(1000);
                countDownLatch.countDown();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
       Thread t2 = new Thread(()->{
            System.out.println("子线程:"+Thread.currentThread().getName());
            try {
                Thread.sleep(10);
                countDownLatch.countDown();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        try {
            t1.start();
            t2.start();
            countDownLatch.await();
            System.out.println("2个子线程已经执行完毕");
            System.out.println("继续执行主线程");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

CountDownLatch 计数器初始值等于2,之后计数器countDown 减一,通过 latch.await() 来实现对计数器等于0的等待。

三.CyclicBarrier

CyclicBarrier,让一组线程到达一个同步点后再一起继续运行,在其中任意一个线程未到达同步点,其他到达的线程均会被阻塞。

/**
 * @Classname CyclicBarrierTest
 * @Description TODO
 * @Date 2020/11/7 15:13
 * @Created by limeng
 * 解决一组线程之间互相等待
 * 让一组线程等待至某个状态之后再全部同步执行,叫做回环是因为当所有等待线程都被释放以后,CycilcBarrier可以被重用,我们暂且把这个状态叫做barrier
 * ,当调用await()方法之后,线程就处于barrier了。
 *
 *
 * parties 聚集数量,保证同步回调函数的数量
 */
public class CyclicBarrierTest {
    public static void main(String[] args) {
        int N = 5;
        CyclicBarrier cyclicBarrier = new CyclicBarrier(N);
        ThreadPoolExecutor pool = ThreadPool.newFixedThreadPool(10, "CyclicBarrierTest", false);
        System.out.println(cyclicBarrier.getParties());
        for (int i = 0; i < N; i++) {
            pool.execute(new Writer(cyclicBarrier));
        }

    }
    static class Writer implements Runnable{
        private  CyclicBarrier cyclicBarrier;
        public Writer(CyclicBarrier cyclicBarrier) {
            this.cyclicBarrier = cyclicBarrier;
        }
        @Override
        public void run() {
            System.out.println("线程:"+Thread.currentThread().getName()+" 正在写入数据");
            try {
                Thread.sleep(1000);
                System.out.println("线程:"+Thread.currentThread().getName() + "写完");
                cyclicBarrier.await();
            } catch (InterruptedException | BrokenBarrierException e) {
                e.printStackTrace();
            }
            System.out.println("所有线程写入完毕,继续处理其他任务");
        }
    }
}

四.总结

CountDownLatch 主要用来解决一个线程等待多个线程的场景。

CyclicBarrier是一组线程之间互相等待。

CountDownLatch计数器是不能循环利用,也就是说一旦计数器减到0,在有线程调用await(),该线程会直接通过,但CyclicBarrier的计数器是可以循环利用的,而且具备自动重置的功能,一旦计数器减到0会自动重置到你设置的初始值,除此之外,CyclicBarrier还可以设置回调函数。

参考

《Java并发编程实战》

公众号

在这里插入图片描述

微信号:bigdata_limeng