zoukankan      html  css  js  c++  java
  • CountDownLatch/CyclicBarrier/Semaphore 使用过吗

    CountDownLatch

    让一些线程堵塞直到另一个线程完成一系列操作后才被唤醒。CountDownLatch 主要有两个方法,当一个或多个线程调用 await 方法时,调用线程会被堵塞,其他线程调用 countDown 方法会将计数减一(调用 countDown 方法的线程不会堵塞),当计数其值变为零时,因调用 await 方法被堵塞的线程会被唤醒,继续执行。

    假设我们有这么一个场景,教室里有班长和其他6个人在教室上自习,怎么保证班长等其他6个人都走出教室在把教室门给关掉。

    public class CountDownLanchDemo {
        public static void main(String[] args) {
            for (int i = 0; i < 6; i++) {
                new Thread(() -> {
                    System.out.println(Thread.currentThread().getName() + " 离开了教室...");
                }, String.valueOf(i)).start();
            }
            System.out.println("班长把门给关了,离开了教室...");
        }
    }
    
    0 离开了教室...
    1 离开了教室...
    2 离开了教室...
    3 离开了教室...
    班长把门给关了,离开了教室...
    5 离开了教室...
    4 离开了教室...

    发现班长都没有等其他人理他教室就把门给关了,此时我们就可以使用 CountDownLatch 来控制

    public class CountDownLanchDemo {
        public static void main(String[] args) throws InterruptedException {
            CountDownLatch countDownLatch = new CountDownLatch(6);
            for (int i = 0; i < 6; i++) {
                new Thread(() -> {
                    countDownLatch.countDown();
                    System.out.println(Thread.currentThread().getName() + " 离开了教室...");
                }, String.valueOf(i)).start();
            }
            countDownLatch.await();
            System.out.println("班长把门给关了,离开了教室...");
        }
    }
    0 离开了教室...
    1 离开了教室...
    2 离开了教室...
    3 离开了教室...
    4 离开了教室...
    5 离开了教室...
    班长把门给关了,离开了教室...
     

    使用枚举完成countDownLatch案例

    @Setter
    @Getter
    public class CountDownLatchDemo {
    
        public static void main(String[] args) throws InterruptedException {
    
            CountDownLatch countDownLatch=new CountDownLatch(6) ;
    
            for (int i = 1; i <=6; i++) {
                new Thread(()->{
                    System.out.println(Thread.currentThread().getName()+"国被灭.......");
                    countDownLatch.countDown();
                },CountryEnum.getcountryEnum(i).getName()+"").start();
            }
    
            countDownLatch.await();
    
            System.out.println(CountryEnum.seven+"国一统华夏");
        }
    }
    
    
    
    @Getter
    enum CountryEnum {
        one(1, "齐", "100", "demaxiya1"),
        two(2, "楚", "100", "demaxiya1"),
        three(3, "燕", "100", "demaxiya1"),
        four(4, "韩", "100", "demaxiya1"),
        five(5, "赵", "100", "demaxiya1"),
        six(6, "巍", "100", "demaxiya1"),
        seven(7, "秦", "100", "demaxiya1");
        private Integer id;
    
        private String name;
        private String time;
        private String beizhu;
    
        CountryEnum(Integer id, String name, String time, String beizhu) {
            this.id = id;
            this.name = name;
            this.time = time;
            this.beizhu = beizhu;
        }
        public static CountryEnum getcountryEnum(Integer id ){
            for (CountryEnum value : values()) {
               if (value.id==id){
                   return value;
               }
            }
            return null;
        }
    }

    打印

    齐国被灭.......
    燕国被灭.......
    楚国被灭.......
    韩国被灭.......
    巍国被灭.......
    赵国被灭.......
    seven国一统华夏

     

    、CyclicBarrier(集齐七颗龙珠召唤神龙)

    1. CycliBarrier

      可循环(Cyclic)使用的屏障。让一组线程到达一个屏障(也可叫同步点)时被阻塞,知道最后一个线程到达屏障时,屏障才会开门,所有被屏障拦截的线程才会继续干活,线程进入屏障通过CycliBarrier的await()方法

    2. 代码示例:

      import java.util.concurrent.BrokenBarrierException;
      import java.util.concurrent.CyclicBarrier;
      
      public class CyclicBarrierDemo {
          public static void main(String[] args) {
              cyclicBarrierTest();
          }
      
          public static void cyclicBarrierTest() {
              CyclicBarrier cyclicBarrier = new CyclicBarrier(7, () -> {
                  System.out.println("====召唤神龙=====");
              });
              for (int i = 1; i <= 7; i++) {
                  final int tempInt = i;
                  new Thread(() -> {
                      System.out.println(Thread.currentThread().getName() + "	收集到第" + tempInt + "颗龙珠");
                      try {
                          cyclicBarrier.await();
                      } catch (InterruptedException e) {
                          e.printStackTrace();
                      } catch (BrokenBarrierException e) {
                          e.printStackTrace();
                      }
                  }, "" + i).start();
              }
          }
      }

      打印

      2 收集到第2颗龙珠
      3 收集到第3颗龙珠
      1 收集到第1颗龙珠
      5 收集到第5颗龙珠
      4 收集到第4颗龙珠
      6 收集到第6颗龙珠
      7 收集到第7颗龙珠
      ====召唤神龙=====

       

      3、Semaphore信号量

      可以代替Synchronize和Lock

      1. 信号量主要用于两个目的,一个是用于多个共享资源的互斥作用,另一个用于并发线程数的控制

      2. 代码示例:

        抢车位示例:

    3. package juc.lock.SemaphoreDemo;
      
      import java.util.concurrent.Semaphore;
      
      /**
       * @Classname SemaphoreDemo
       * @Description TODO
       * @Date 2020/7/13 23:03
       * @Created by imp
       */
      public class SemaphoreDemo {
      
          public static void main(String[] args) {
              Semaphore semaphore=new Semaphore(3); //3个车位
      
              for (int i = 0; i < 6; i++) {
                  new Thread(()->{
                      try {
                          //抢占车位
                          semaphore.acquire();
                          System.out.println(Thread.currentThread().getName()+"	抢占到车位");
                          Thread.sleep(2000);
                          System.out.println(Thread.currentThread().getName()+"	停两秒钟离开");
                      } catch (InterruptedException e) {
                          e.printStackTrace();
                      }finally {
                          semaphore.release();
                      }
                  },String.valueOf(i)).start();
              }
          }
      }

      打印:

      0 抢占到车位
      1 抢占到车位
      4 抢占到车位
      0 停两秒钟离开
      5 抢占到车位
      1 停两秒钟离开
      4 停两秒钟离开
      2 抢占到车位
      3 抢占到车位
      5 停两秒钟离开
      3 停两秒钟离开
      2 停两秒钟离开

       
  • 相关阅读:
    C# 异常处理
    UIElement 的DesiredSize 和 RenderSize
    删除集合中满足条件的元素
    C# 中的Property
    C# readonly 与 const
    C# 实例化类的执行顺序
    C# volatile 与 lock
    双重检查加锁机制
    定位问题
    EBS部分表整理
  • 原文地址:https://www.cnblogs.com/hejunhong/p/13296526.html
Copyright © 2011-2022 走看看