benym的知识笔记 benym的知识笔记
🦮首页
  • Java

    • Java-基础
    • Java-集合
    • Java-多线程与并发
    • Java-JVM
    • Java-IO
  • Python

    • Python-基础
    • Python-机器学习
  • Kafka
  • Redis
  • MySQL
  • 分布式事务
  • Spring

    • SpringIOC
    • SpringAOP
🦌设计模式
  • 剑指Offer
  • LeetCode
  • 排序算法
🐧实践
  • Rpamis

    • Utils
    • Exception
    • Security
  • 归档
  • 标签
  • 目录
🦉里程碑
🐷关于
GitHub (opens new window)

benym

惟其艰难,才更显勇毅🍂惟其笃行,才弥足珍贵
🦮首页
  • Java

    • Java-基础
    • Java-集合
    • Java-多线程与并发
    • Java-JVM
    • Java-IO
  • Python

    • Python-基础
    • Python-机器学习
  • Kafka
  • Redis
  • MySQL
  • 分布式事务
  • Spring

    • SpringIOC
    • SpringAOP
🦌设计模式
  • 剑指Offer
  • LeetCode
  • 排序算法
🐧实践
  • Rpamis

    • Utils
    • Exception
    • Security
  • 归档
  • 标签
  • 目录
🦉里程碑
🐷关于
GitHub (opens new window)
  • Java-基础

    • Java反射获取类对象的三种方式
    • 动态代理
  • Java-集合

    • ArrayList的扩容机制
  • Java-多线程与并发

    • Java多线程实现的几种方式
    • 多线程交替打印数字—多种实现
    • CountDownLatch使用方法
      • CyclicBarrier使用方法
      • Semaphore使用方法
      • CompletableFuture常用用法及踩坑
    • Java-JVM

      • 自定义类加载器
      • JMH-基准测试框架
    • Java-IO

      • 概览
    • Java
    • Java-多线程与并发
    benym
    2022-01-18
    目录

    CountDownLatch使用方法

    # CountDownLatch使用方法

    CountDownLatch是JUC包中的一个同步工具类,允许一个或多个线程等待,直到其他线程执行完毕之后再执行。

    # 应用场景

    CountDownLatch通常有两种使用场景:

    • 场景1. 让多个线程等待——强调多个线程的最大并行性,即多个线程在同一时刻开始执行,类似赛跑场景,多个线程都在起点,等待发令后同时开跑,只需初始化1个计数器
    • 场景2. 让一个线程等待——主线程等待其他n个线程执行完毕之后进行执行,需要初始化n个计数器

    # 基本原理

    • 创建 CountDownLatch 并设置计数器值。
    • 启动多线程并且调用 CountDownLatch 实例的 countDown() 方法。
    • 主线程调用 await()方法,主线程的操作就会在这个方法上阻塞,直到其他线程完成各自的任务,count 值为 0,停止阻塞,主线程继续执行。

    # 使用方法

    # 场景1:最大并行性,多个线程就绪同时执行

    在这个场景中,CountDownLatch可类似于发令者的角色

    public class Test {
    
        public static void main(String[] args) throws InterruptedException{
            
            CountDownLatch count = new CountDownLatch(1);
            for (int i = 0; i < 8; i++) {
                new Thread(() -> {
                    try {
                        // 线程阻塞,等待所有线程就绪
                        count.await();
                        System.out.println(Thread.currentThread().getName());
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }).start();
            }
            count.countDown(); // 计数器减1,多个线程开始同时执行
            System.out.println("主线程打印");
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20

    运行结果

    主线程打印
    Thread-3
    Thread-6
    Thread-4
    Thread-5
    Thread-1
    Thread-0
    Thread-7
    Thread-2
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    1
    2
    3
    4
    5
    6
    7
    8
    9

    通过count.await()使当前线程等待,直到计数器为0,或者线程被中断。由于count.countDown()在循环外部,每个线程启动的时候都会将自己阻塞,但此时的阻塞并没有阻塞主线程,所以主线程打印先一步执行,在循环内8个线程就绪之后,通过计数器减1,让他们同步执行打印,达到并行执行的目的。

    # 场景2:让单个线程等待其他多个线程执行完毕后,再执行
    public class Test {
    
        public static void main(String[] args) throws InterruptedException {
            CountDownLatch count = new CountDownLatch(8);
            for (int i = 0; i < 8; i++) {
                new Thread(() -> {
                    System.out.println(Thread.currentThread().getName());
                    count.countDown();
                }).start();
            }
            count.await();
            System.out.println("主线程打印");
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14

    运行结果

    Thread-0
    Thread-2
    Thread-1
    Thread-3
    Thread-4
    Thread-5
    Thread-6
    Thread-7
    主线程打印
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    1
    2
    3
    4
    5
    6
    7
    8
    9

    count.await()在循环外部,阻塞主线程等待其他8个线程执行count.countDown(),当计数器为0时,才执行主线程打印

    # CountDownLatch与CyclicBarrier的区别

    CountDownLatch和CyclicBarrier都能够实现线程之间的等待,只不过它们侧重点不同:

    • CountDownLatch一般用于一个或多个线程,等待其他线程执行完任务后,再才执行
    • CyclicBarrier一般用于一组线程互相等待至某个状态,然后这一组线程再同时执行 另外,CountDownLatch是减计数,计数减为0后不能重用;而CyclicBarrier是加计数,可置0后复用。
    编辑 (opens new window)
    #Java#JUC
    上次更新: 2023/05/13, 18:05:21
    多线程交替打印数字—多种实现
    CyclicBarrier使用方法

    ← 多线程交替打印数字—多种实现 CyclicBarrier使用方法→

    最近更新
    01
    SpringCache基本配置类
    05-16
    02
    DSTransactional与Transactional事务混用死锁场景分析
    03-04
    03
    Rpamis-security-原理解析
    12-13
    更多文章>
    Theme by Vdoing | Copyright © 2018-2024 benym | MIT License
     |   |   | 
    渝ICP备18012574号 | 渝公网安备50010902502537号
    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式