zoukankan      html  css  js  c++  java
  • java 中 CountDownLatch、CyclicBarrier 和 Semaphore 的简单使用

    一、CountDownLatch

    1.1 概述

           让一些线程阻塞直到另外一些完成后才被唤醒。

           该类主要有两个方法,当一个或多个线程调用 await 方法时,调用线程会被阻塞。其他线程调用 countDown方法计数器减1(调用countDown方法时线程不会阻塞),当计数器的值变为0,因调用 await 方法被阻塞的线程会被唤醒继续执行。

    1.2 模拟场景

           有 6 名学生上完课后,离开教室,但他们离开的时间不相同,班长需要最后一个离开,锁上教室的门。

    1.3 程序模拟

    1.3.1 使用 CountDownLatch 之前

      1 public void closeDoor() {
      2 
      3     for (int i = 1; i <= 6; i++) {
      4         new Thread(() -> {
      5             System.out.println(Thread.currentThread().getName() + " 离开教室");
      6         }, String.valueOf(i)).start();
      7     }
      8 
      9     System.out.println(Thread.currentThread().getName() + " 班长锁门离开教室");
     10 }

    image

    1.3.2 使用 CountDownLatch 之后

      1 public void closeDoor() throws InterruptedException {
      2     CountDownLatch countDownLatch = new CountDownLatch(6);
      3 
      4     for (int i = 1; i <= 6; i++) {
      5         new Thread(() -> {
      6             System.out.println(Thread.currentThread().getName() + " 离开教室");
      7             countDownLatch.countDown();
      8         }, String.valueOf(i)).start();
      9     }
     10 
     11     countDownLatch.await();
     12     System.out.println(Thread.currentThread().getName() + " 班长锁门离开教室");
     13 }

    image

    1.4 CountDownLatch 配合枚举类的使用

      1 private static void nationalUnification() throws InterruptedException {
      2     CountDownLatch countDownLatch = new CountDownLatch(6);
      3 
      4     for (int i = 1; i <= 6; i++) {
      5         new Thread(() -> {
      6             System.out.println(Thread.currentThread().getName() + "国被灭...");
      7             countDownLatch.countDown();
      8         }, CountryEnum.forEachCountryEnum(i).getCountry()).start();
      9     }
     10 
     11     countDownLatch.await();
     12     System.out.println(Thread.currentThread().getName() + " 秦国灭六国,一统华夏");
     13 }
     14 
     15 // 枚举类,存储国家的名字
     16 public enum CountryEnum {
     17 
     18     ONE(1, ""),
     19     TWO(2, ""),
     20     THREE(3, ""),
     21     FOUR(4, ""),
     22     FIVE(5, ""),
     23     SIX(6, "");
     24 
     25     private Integer code;
     26     private String country;
     27 
     28     CountryEnum(Integer code, String country) {
     29         this.code = code;
     30         this.country = country;
     31     }
     32 
     33     public Integer getCode() {
     34         return code;
     35     }
     36 
     37     public String getCountry() {
     38         return country;
     39     }
     40 
     41     public static CountryEnum forEachCountryEnum(int index) {
     42         CountryEnum[] countryEnums = CountryEnum.values();
     43         for (CountryEnum element : countryEnums) {
     44             if (element.getCode() == index) {
     45                 return element;
     46             }
     47         }
     48         return null;
     49     }
     50 }
     51 
    image

    二、CyclicBarrier

    2.1 概述

           CyclicBarrier 的字面意思是可循环(Cyclic),使用的屏障(barrier)。它要做的事情是,让一组线程到达一个屏障(也可以叫做同步点)时被阻塞,直到最后一个线程到达屏障时,屏障才会开门,所有被屏障拦截的线程才会继续干活,线程进入屏障通过 CyclicBarrier 的 await() 方法。

    2.2 示例

      1 public void meet() {
      2     CyclicBarrier cyclicBarrier = new CyclicBarrier(10, () -> {
      3         System.out.println("人齐了,准备开会");
      4     });
      5 
      6     for (int i = 1; i <= 10; i++) {
      7         new Thread(() -> {
      8             System.out.println(Thread.currentThread().getName() + " 来到会议室");
      9             try {
     10                 cyclicBarrier.await();
     11             } catch (InterruptedException | BrokenBarrierException e) {
     12                 e.printStackTrace();
     13             }
     14         }, String.valueOf(i)).start();
     15     }
     16 }
    image

    三、Semaphore

    3.1 概述

           A counting semaphore. Conceptually, a semaphore maintains a set of permits. Each acquire() blocks if necessary until a permit is available, and then takes it. Each release() adds a permit, potentially releasing a blocking acquirer. However, no actual permit objects are used; the Semaphore just keeps a count of the number available and acts accordingly.

    3.2 示例

      1 public void semaphoreTest() {
      2     Semaphore semaphore = new Semaphore(3);
      3 
      4     for (int i = 1; i <= 6; i++) {
      5         new Thread(() -> {
      6             try {
      7                 semaphore.acquire();
      8                 System.out.println(Thread.currentThread().getName() + " 抢到车位...");
      9                 TimeUnit.SECONDS.sleep(3);
     10                 System.out.println(Thread.currentThread().getName() + "停车3秒,离开车位");
     11             } catch (InterruptedException e) {
     12                 e.printStackTrace();
     13             } finally {
     14                 semaphore.release();
     15             }
     16         }, String.valueOf(i)).start();
     17     }
     18 }
    image
  • 相关阅读:
    低功耗蓝牙配对绑定解读和实践
    低功耗蓝牙ATT/GATT/Profile/Service/Characteristic规格解读
    Nordic官方网络资源介绍(官网/devzone/GitHub)
    板子功耗高的原因有哪些
    同样的代码在官方开发板上运行正常,在自己板子上就跑不起来,怎么办
    如何理解nRF5芯片外设PPI
    nRF5芯片外设GPIO和GPIOTE介绍
    定时模块app_timer用法及常见问题—nRF5 SDK模块系列二
    Flash访问模块FDS用法及常见问题—nRF5 SDK模块系列一
    nRF5 SDK软件架构及softdevice工作原理
  • 原文地址:https://www.cnblogs.com/lveyHang/p/11906226.html
Copyright © 2011-2022 走看看