zoukankan      html  css  js  c++  java
  • 【Java并发】闭锁 CountDownLatch 和 回环栅栏CyclicBarrier

    这两个目的都是为了等待所有线程任务执行完之后再执行其他任务。

    与CyclicBarrier不同的是,CountDownLatch等待的是一组线程执行完之后,才开始执行其他任务,而这一组线程之间相互不影响;而CyclicBarrier则是等待一组线程全部执行完之后才执行其他任务,这里等待是只一组线程之间的相互等待,线程之间有相互影响。并且CyclicBarrier是可复用的,而CountDownLatch则不能,同时CyclicBarrier是递增的方式,而CountDownLatch是递减的方式计数。

    CountDownLatch例子:

        public class CountDownLatchTest {
            static Logger logger = Logger.getLogger("console");
            public static void main(String[] args) throws InterruptedException {
                int N = 5;
                CountDownLatch latch = new CountDownLatch(N);
                for (int i=0;i<N;i++){
                    new Thread(new MyThread(latch),"线程"+i).start();
                }
                System.out.println(Thread.currentThread().getName()+"等待其他线程执行");
                latch.await();
                System.out.println(Thread.currentThread().getName()+":线程执行完毕,执行其他任务");
            }
            static class MyThread implements Runnable{
                private CountDownLatch latch;
                public MyThread(CountDownLatch latch){
                    this.latch = latch;
                }
                @Override
                public void run() {
                    try {
                        System.out.println(Thread.currentThread().getName()+"开始执行");
                        Thread.sleep(new Random().nextInt(1000));
                        latch.countDown();
                        System.out.println(Thread.currentThread().getName()+"执行结束");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        //输出
        main等待其他线程执行
        线程0开始执行
        线程3开始执行
        线程1开始执行
        线程4开始执行
        线程2开始执行
        线程3执行结束
        线程1执行结束
        线程0执行结束
        线程4执行结束
        线程2执行结束
        main:线程执行完毕,执行其他任务

    CyclicBarrie例子:

        public class CyclicBarrieTest {
            public static void main(String[] args) throws InterruptedException, BrokenBarrierException {
                int N = 5;
                System.out.println(Thread.currentThread().getName()+"开始执行");
                CyclicBarrier barrier = new CyclicBarrier(N, new Runnable() {
                    @Override
                    public void run() {
                        System.out.println(Thread.currentThread().getName()+":线程执行完,执行其他任务");
                    }
                });
                for (int i=0;i<N;i++){
                    new Thread(new CyclicBarrieTest.MyThread(barrier),"线程"+i).start();
                }
                System.out.println(Thread.currentThread().getName()+"执行结束");
    
                /////复用///
                Thread.sleep(2000);
                System.out.println("--------CyclicBarrieTest复用-------");
                for (int i=0;i<N;i++){
                    new Thread(new CyclicBarrieTest.MyThread(barrier),"线程"+i).start();
                }
            }
            static class MyThread implements Runnable{
                private CyclicBarrier barrier;
                public MyThread(CyclicBarrier barrier){
                    this.barrier = barrier;
                }
                @Override
                public void run() {
                    try {
                        System.out.println(Thread.currentThread().getName()+"开始执行");
                        Thread.sleep(new Random().nextInt(1000));
                        System.out.println(Thread.currentThread().getName()+"执行结束");
                        barrier.await();
                    } catch (InterruptedException | BrokenBarrierException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        //输出
        main开始执行
        main执行结束
        线程0开始执行
        线程1开始执行
        线程2开始执行
        线程4开始执行
        线程3开始执行
        线程2执行结束
        线程0执行结束
        线程4执行结束
        线程1执行结束
        线程3执行结束
        线程3:线程执行完,执行其他任务
        --------CyclicBarrieTest复用-------
        线程0开始执行
        线程1开始执行
        线程2开始执行
        线程3开始执行
        线程4开始执行
        线程0执行结束
        线程4执行结束
        线程3执行结束
        线程1执行结束
        线程2执行结束
        线程2:线程执行完,执行其他任务

    可以看到CyclicBarrie是可复用的,在达到最大计数只后会自动重新计数。并且CyclicBarrieTest的构造方法的第二个参数线程是用最后一个到达的线程去执行的。


    使用场景:

    CountDownLatch:适合在主线程需要等待子线程执行完毕后在执行或者需要等待某些资源的时候。

    CyclicBarrier:适合需要线程相互等待对方完成时,比如多线程计算,在对计算结果进行汇总。

  • 相关阅读:
    Oracle数据库部分迁至闪存存储方案
    RAC环境下误操作将数据文件添加到本地存储
    Oracle的窗口和自动任务
    ####### Scripts Summary #######
    plsql 操纵表数据的2种方式
    css 如何使图片与文字在div中居中展示?
    eclipse svn新增文件不显示在文件列表,只有修改文件可以提交!
    js 正则表达式校验必须包含字母、数字、特殊字符
    css 禁止录入中文
    POJ 1740:A New Stone Game
  • 原文地址:https://www.cnblogs.com/cnsec/p/13286690.html
Copyright © 2011-2022 走看看