• Java CountDownLatch应用


          Java的concurrent包里面的CountDownLatch其实可以把它看作一个计数器,只不过这个计数器的操作是原子操作,同时只能有一个线程去操作这个计数器,也就是同时只能有一个线程去减这个计数器里面的值。

          你可以向CountDownLatch对象设置一个初始的数字作为计数值,任何调用这个对象上的await()方法都会阻塞,直到这个计数器的计数值被其他的线程减为0为止。

          CountDownLatch的一个非常典型的应用场景是:有一个任务想要往下执行,但必须要等到其他的任务执行完毕后才可以继续往下执行。假如我们这个想要继续往下执行的任务调用一个CountDownLatch对象的await()方法,其他的任务执行完自己的任务后调用同一个CountDownLatch对象上的countDown()方法,这个调用await()方法的任务将一直阻塞等待,直到这个CountDownLatch对象的计数值减到0为止。

          举个例子,有三个工人在为老板干活,这个老板有一个习惯,就是当三个工人把一天的活都干完了的时候,他就来检查所有工人所干的活。记住这个条件:三个工人先全部干完活,老板才检查。所以在这里用Java代码设计两个类,Worker代表工人,Boss代表老板,具体的代码实现如下:

    //工人类
    class Worker implements Runnable {
    
        private CountDownLatch countDownLatch;
        private String name;
    
        public Worker(CountDownLatch countDownLatch, String name) {
            this.countDownLatch = countDownLatch;
            this.name = name;
        }
    
        @Override
        public void run() {
            this.work();
            try {
                TimeUnit.SECONDS.sleep(new Random().nextInt(10));
            } catch (InterruptedException e) {
            } finally {
                this.countDownLatch.countDown(); //闭锁计数器减一
            }
        }
    
        private void work() {
            System.out.println(this.name + "正在干活。");
        }
    
    }
    

      

    //老板类
    class Boss implements Runnable {
    
        private CountDownLatch countDownLatch;
    
        public Boss(CountDownLatch countDownLatch) {
            this.countDownLatch = countDownLatch;
        }
    
        @Override
        public void run() {
            System.out.println("老板正在等待所有公认干完活....");
            try {
                this.countDownLatch.await();
            } catch (InterruptedException e) {
            }
            System.out.println("工人们都干完活了,老板开始检查了!!!!!!!!!!!!!!");
        }
    }
    /**
     * 闭锁测试
     * Created by gan on 2019/5/18 22:47.
     */
    public class CountDownLatchDemo {
    
        public static void main(String[] args) {
            ExecutorService executor = Executors.newCachedThreadPool();
            CountDownLatch countDownLatch = new CountDownLatch(3);
    
    
            Boss b1 = new Boss(countDownLatch);
            Worker w1 = new Worker(countDownLatch, "小王");
            Worker w2 = new Worker(countDownLatch, "校长");
            Worker w3 = new Worker(countDownLatch, "小李");
    
            executor.execute(b1);
            executor.execute(w1);
            executor.execute(w2);
            executor.execute(w3);
    
            executor.shutdown();
        }
    }

    当你运行CountDownLatchDemo这个对象的时候,你会发现是等所有的工人都干完了活,老板才来检查,下面是我本地机器上运行的一次结果,可以肯定的每次运行的结果可能与下面不一样,但老板检查永远是在后面的。

     

    同样还可以完成如下功能: "将一个大任务分解为几个小任务用多线程跑,最后统计完成时间" 功能,代码如下:

     1 /**
     2  * Created by gan on 2019/5/19 0:05.
     3  */
     4 public class CountDownLatchDemo2 {
     5 
     6     public static void main(String[] args) throws InterruptedException {
     7         final CountDownLatch countDownLatch = new CountDownLatch(10);
     8         long start = System.currentTimeMillis();
     9 
    10         for (int i = 0; i < 10; i++) {
    11             int j = i;
    12             new Thread(() -> {
    13                 try {
    14                     TimeUnit.SECONDS.sleep(1);
    15                     System.out.println(Thread.currentThread().getName() + "执行完毕....." + j);
    16                 } catch (InterruptedException e) {
    17                 } finally {
    18                     countDownLatch.countDown();
    19                 }
    20             }).start();
    21         }
    22 
    23         System.out.println("主线程等待子线程完成。。。。");
    24         countDownLatch.await(); //主线程到此进入阻塞状态,等待 countDownLatch.countDown()减为0后才进入就绪->执行
    25         System.out.println("所有线程执行完毕,一共耗时===================>" + (System.currentTimeMillis() - start));
    26 
    27     }
    28 }

    运行结果如下:

    参考文章: https://zapldy.iteye.com/blog/746458

  • 相关阅读:
    POJ-3468 A Simple Problem with Integers(线段树、段变化+段查询、模板)
    CSUOJ-1978 LXX的图论题(最短路、Bellman-Ford判断负圈)
    CSU-1975 机器人搬重物(BFS)
    POJ-3522 Slim Span(最小生成树)
    POJ-1733 Parity game (并查集)
    libmysqlclient.so.16未找到方法
    python 不同目录间的模块调用
    python模块详解 logging
    python模块详解 re
    python模块详解 hashlib
  • 原文地址:https://www.cnblogs.com/ganbo/p/10887774.html
Copyright © 2020-2023  润新知