zoukankan      html  css  js  c++  java
  • 多线程之CountDownLatch和CyclicBarriar使用

      CountDownLatch和CyclicBarriar是java.util.concurrent包下面提供的多线程同步工具,两者有点相似,相当于计数器,但是用处还是有区别的。

      CountDownLatch:用于在完成一组正在其它线程中执行的操作之前,它允许一个或多个线程一直等待,await()表示等待,等到其它线程全部执行结束后(即通过countDown()方法来减数,计数为0,即其它线程执行完毕)然后继续执行,示例代码:

    public static void main(String[] args) {
            //该计数器初始值1,用于主线程发送命令
            final CountDownLatch latch1 = new CountDownLatch(1);
            //该计数器初始值为2,用于响应命令接受完成
            final CountDownLatch latch2 = new CountDownLatch(2);
            //创建一个大小为2线程池
            ExecutorService executor = Executors.newCachedThreadPool(); 
            for (int i = 0; i < 2; i++) {
                executor.submit(new Runnable() {
                    public void run() {
                        try {
                            System.out.println("线程" + Thread.currentThread().getName() + "正准备接受命令");
                            //等待主线程发送命令
                            latch1.await();
                            System.out.println("线程" + Thread.currentThread().getName() + "已接受命令");
                            Thread.sleep((long) (Math.random() * 10000));
                            System.out.println("线程" + Thread.currentThread().getName() + "回应命令处理结果");
                            //命令接受完毕,返回给主线程,latch2减1。
                            latch2.countDown();
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                });
            }
            try {
                Thread.sleep((long) (Math.random() * 10000));
                System.out.println("线程" + Thread.currentThread().getName() + "即将发布命令");
                //发送命令,latch1计数减1
                latch1.countDown(); 
                System.out.println("线程" + Thread.currentThread().getName() + "已发送命令,正在等待响应");
                //命令发送后处于等待状态,其它线程全部响应完成,也就是latch2.countDown(),再继续执行
                latch2.await(); 
                System.out.println("线程" + Thread.currentThread().getName() + "已收到所有响应结果");
            } catch (Exception e) {
                e.printStackTrace();
            }
            //关闭线程池
            executor.shutdown(); 
        }

      CyclicBarriar:用于多个线程在一个指定的公共屏障点(或者说集合点)相互等待,await()方法代表屏障点,每次调用await(),计数(创建CyclicBarriar对象时传入int类型的参数,表示初始计数)减一,直到减到0后,表示所有线程都抵达,然后开始执行后面的任务,示例代码:

    public static void main(String[] args) throws Exception {
            //创建CyclicBarrier对象并设置2个公共屏障点
            final CyclicBarrier barrier = new CyclicBarrier(2);
            //创建大小为2的线程池
            ExecutorService executor = Executors.newFixedThreadPool(2);
            for (int i = 0; i < 2; i++) {
                executor.submit(new Runnable() {
                    public void run() {
                        try {
                            Thread.sleep((long)(Math.random()*10000));
                            System.out.println("线程" + Thread.currentThread().getName() + "即将到达集合地点1,当前已有"
                                    + barrier.getNumberWaiting() + "个已经到达,正在等候");
                            //如果没有达到公共屏障点,则该线程处于阻塞状态,如果达到公共屏障点则所有处于等待的线程都继续往下运行
                            barrier.await();
                            
                            System.out.println("线程" + Thread.currentThread().getName() + "通过集合地点1");
                            
                            Thread.sleep((long)(Math.random()*10000));
                            System.out.println("线程" + Thread.currentThread().getName() + "即将到达集合地点2,当前已有"
                                    + barrier.getNumberWaiting() + "个已经到达,正在等候");
                            barrier.await();
                            
                            System.out.println("线程" + Thread.currentThread().getName() + "通过集合地点2");
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                });
            }
            //关闭线程池
            executor.shutdown();
        }

      注意:观察CyclicBarrier的使用可以发现,它计数减至0后,计数器会被重置,可以再次使用,可能这也是它被定义为Cyclic(周期的、循环的)原因,这个是和CountDownLatch区别的地方。

  • 相关阅读:
    读取.properties配置文件的方式
    使用二维数组打印10行的杨辉三角
    【三】Django模版的使用
    【二】Django 视图和url配置
    初学Django
    Java ------ 工厂模式、单例模式
    总结各种排序算法【Java实现】
    MyBatis --- 动态SQL、缓存机制
    MyBatis --- 映射关系【一对一、一对多、多对多】,懒加载机制
    SSM框架搭建
  • 原文地址:https://www.cnblogs.com/handsomeye/p/6421394.html
Copyright © 2011-2022 走看看