Java并发工具类详解:CountDownLatch与CyclicBarrier

内容概述

在现代并发编程中,线程的协调和同步至关重要。Java提供了丰富的工具来处理线程同步,其中CountDownLatchCyclicBarrier 是两种常用的并发工具类。它们都存在于java.util.concurrent包中,虽然都有线程协调的功能,但其使用场景和实现机制有所不同。

本文将深入介绍这两种工具类,详细探讨它们的使用场景、实现原理,并通过代码示例帮助您更好地理解和掌握这两种工具的应用。

学习目标

通过学习本文,您将能够:

  • 了解 CountDownLatchCyclicBarrier 的适用场景。
  • 掌握这两种工具类的基本用法和实现原理。
  • 能够在实际开发中使用这些工具类来解决复杂的线程同步问题。

1. CountDownLatch:计数器倒数锁

概念

CountDownLatch 是一个用于让一个或多个线程等待其他线程完成某些操作的同步工具。它通过一个倒数计数器来实现这一功能。当计数器到达零时,所有阻塞等待的线程将被释放,继续执行。

使用场景

  • 线程协作:主线程需要等待多个工作线程完成任务后再继续执行。
  • 等待某些前置任务完成:例如,主线程需要等待系统初始化或数据加载完成,才能继续处理其他任务。

主要方法

  • await():使调用该方法的线程等待,直到倒数计数器减为零。
  • countDown():倒数计数器减一,每当一个任务完成时调用一次。

实现原理

CountDownLatch 通过内部维护一个共享的倒数计数器,多个线程可以调用countDown()方法减少计数。当计数器达到0时,所有因调用await()方法而等待的线程将被释放,恢复执行。

示例代码

import java.util.concurrent.CountDownLatch;

public class CountDownLatchExample {

    public static void main(String[] args) throws InterruptedException {
        int threadCount = 3;
        CountDownLatch latch = new CountDownLatch(threadCount);

        // 创建并启动3个线程
        for (int i = 0; i < threadCount; i++) {
            new Thread(new Worker(latch)).start();
        }

        // 主线程等待所有工作线程完成
        latch.await();
        System.out.println("所有线程已完成,主线程继续执行");
    }

    static class Worker implements Runnable {
        private CountDownLatch latch;

        public Worker(CountDownLatch latch) {
            this.latch = latch;
        }

        @Override
        public void run() {
            try {
                System.out.println(Thread.currentThread().getName() + " 正在执行任务...");
                Thread.sleep(1000);  // 模拟任务执行时间
                System.out.println(Thread.currentThread().getName() + " 完成任务");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                latch.countDown();  // 任务完成后计数器减1
            }
        }
    }
}
输出示例:
Thread-0 正在执行任务...
Thread-1 正在执行任务...
Thread-2 正在执行任务...
Thread-0 完成任务
Thread-1 完成任务
Thread-2 完成任务
所有线程已完成,主线程继续执行

2. CyclicBarrier:循环栅栏

概念

CyclicBarrier 用于让一组线程互相等待,直到所有线程都到达某个屏障点 。与CountDownLatch不同的是,CyclicBarrier可以多次使用,即屏障被打开后可以重置,允许线程再次进入。

使用场景

  • 多线程同步:多个线程在某个任务的某个阶段需要同步,然后继续下一阶段。
  • 阶段性任务:任务分阶段执行,每个阶段结束时需要等待所有线程到达,再进入下一个阶段。

主要方法

  • await():表示当前线程到达了屏障点,等待其他线程都到达后一起继续执行。

实现原理

CyclicBarrier 通过维护一个计数器记录有多少线程调用了await(),每当一个线程到达时,计数器减一。当所有线程到达时,屏障被触发,所有等待的线程继续执行。屏障可以重复使用,即所有线程突破屏障后,它会自动重置。

示例代码

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

public class CyclicBarrierExample {

    public static void main(String[] args) {
        int threadCount = 3;
        CyclicBarrier barrier = new CyclicBarrier(threadCount, new Runnable() {
            @Override
            public void run() {
                System.out.println("所有线程已到达屏障点,执行屏障操作");
            }
        });

        // 创建并启动3个线程
        for (int i = 0; i < threadCount; i++) {
            new Thread(new Worker(barrier)).start();
        }
    }

    static class Worker implements Runnable {
        private CyclicBarrier barrier;

        public Worker(CyclicBarrier barrier) {
            this.barrier = barrier;
        }

        @Override
        public void run() {
            try {
                System.out.println(Thread.currentThread().getName() + " 正在执行任务...");
                Thread.sleep(1000);  // 模拟任务执行时间
                System.out.println(Thread.currentThread().getName() + " 到达屏障点");
                barrier.await();  // 等待其他线程到达屏障点
                System.out.println(Thread.currentThread().getName() + " 突破屏障继续执行");
            } catch (InterruptedException | BrokenBarrierException e) {
                e.printStackTrace();
            }
        }
    }
}
输出示例:
Thread-0 正在执行任务...
Thread-1 正在执行任务...
Thread-2 正在执行任务...
Thread-0 到达屏障点
Thread-1 到达屏障点
Thread-2 到达屏障点
所有线程已到达屏障点,执行屏障操作
Thread-0 突破屏障继续执行
Thread-1 突破屏障继续执行
Thread-2 突破屏障继续执行

3. CountDownLatch与CyclicBarrier的对比

特性 CountDownLatch CyclicBarrier
主要功能 等待其他线程完成任务,倒数计数器为零时释放 线程等待彼此到达同步点,继续执行
重用性 不能重用 可以重用
计数器变化方式 计数器只能递减,无法重置 计数器可以重置,每次都可以再次使用
适用场景 线程协作,等待所有线程完成 多线程阶段同步,线程互相等待

总结

CountDownLatchCyclicBarrier 都是Java并发编程中常用的线程同步工具。CountDownLatch 更适合于一次性的线程协调 ,如等待多个线程完成任务;而CyclicBarrier 则适合阶段性的同步,允许线程在某些阶段定期同步后继续执行。理解和掌握这些工具类,可以帮助开发者更好地处理复杂的线程同步问题,提高多线程程序的可控性和性能。

通过本文,您应该能够选择合适的工具类来实现多线程任务的同步与协调。


学习目标达成 :你现在应该能够使用 CountDownLatchCyclicBarrier 实现复杂的线程同步操作,合理地协调多线程之间的执行顺序。

相关推荐
白总Server10 分钟前
MySQL在大数据场景应用
大数据·开发语言·数据库·后端·mysql·golang·php
c语言鹌鹑蛋11 分钟前
C++进阶 --- 多继承中的虚表问题
开发语言·c++
姑苏老陈17 分钟前
【Python基础】Python文件处理
开发语言·python·python文件操作
luoluoal19 分钟前
java项目之企业级工位管理系统源码(springboot)
java·开发语言·spring boot
ch_s_t21 分钟前
新峰商城之购物车(一)
java·开发语言
yukai0800825 分钟前
Python 全栈系列271 微服务踩坑记
python·微服务·php
蜜桃小阿雯26 分钟前
JAVA开源项目 校园美食分享平台 计算机毕业设计
java·jvm·spring boot·spring cloud·intellij-idea·美食
黄昏_29 分钟前
苍穹外卖Day01-2
java·spring
努力的八爪鱼41 分钟前
记录工作中遇到的问题(持续更新~)
java
求学小火龙43 分钟前
ElasticSearch介绍+使用
java·大数据·elasticsearch