Java中CountdownLatch的用法与底层原理详解

编程探索课程 2024-09-12 14:44:55
引言

在Java并发编程中,CountdownLatch 是一个非常实用的同步工具类,它允许一个或多个线程等待其他线程完成一组操作后再继续执行。这种机制在需要等待多个线程完成任务时非常有用,比如初始化数据、加载资源文件等场景。

本文将从CountdownLatch的用法和底层原理两个方面进行详细介绍。

CountdownLatch的用法基本概念

CountdownLatch 初始化时设置一个计数器,该计数器表示需要等待的线程数量。每当有一个线程完成了任务,就将计数器减1。当计数器减至0时,那些因为调用await()方法而等待的线程就会被唤醒,继续执行后面的代码。

主要方法CountdownLatch(int count):构造函数,初始化计数器的值。void countDown():将计数器的值减1。如果计数器的值变为0,则所有等待的线程都会被唤醒。void await():使当前线程在锁存器倒计数至零之前一直等待,除非线程被中断。boolean await(long timeout, TimeUnit unit):使当前线程在锁存器倒计数至零之前一直等待,或者超出了指定的等待时间,则返回false。如果在等待过程中被中断,则抛出InterruptedException。使用示例

假设我们有一个场景,需要等待5个线程完成任务后再继续执行。下面是一个简单的使用示例:

import java.util.concurrent.CountDownLatch;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;public CountdownLatchDemo { public static void main(String[] args) throws InterruptedException { int threadCount = 5; CountdownLatch latch = new CountdownLatch(threadCount); ExecutorService executor = Executors.newFixedThreadPool(threadCount); for (int i = 0; i < threadCount; i++) { executor.submit(() -> { try { // 模拟任务执行 Thread.sleep(1000); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } // 任务完成,计数器减1 latch.countDown(); System.out.println("任务执行完成,剩余等待线程数:" + latch.getCount()); }); } // 等待所有任务完成 latch.await(); System.out.println("所有任务执行完成,继续执行后续操作..."); executor.shutdown(); }}CountdownLatch的底层原理类继承关系

CountdownLatch 类实现了java.util.concurrent.locks.AbstractQueuedSynchronizer(简称AQS)类的一个子类,它利用AQS提供的共享锁(Shared Lock)机制来实现计数器的同步操作。

AQS简介

AQS 是一个用于构建锁和其他同步类的框架。它提供了一个FIFO(先进先出)队列来管理那些已经被阻塞的线程,并且提供了一个共享的int状态值来表示锁的状态或计数器的值。CountdownLatch 使用AQS的共享锁机制,将计数器的值作为AQS的状态值。

核心实现状态值(State):在CountdownLatch中,AQS的状态值用于表示需要等待的线程数量(即计数器的值)。countDown() 方法:通过调用AQS的tryReleaseShared(int releases)方法将计数器的值减1。如果减1后的值为0,则表示所有线程都已经完成任务,此时会唤醒那些因调用await()方法而阻塞的线程。await() 方法:调用AQS的acquireSharedInterruptibly(int arg)方法使当前线程进入等待状态。如果计数器的值不为0,则线程会被放入AQS的等待队列中。一旦计数器的值变为0,或者线程在等待过程中被中断,线程就会从等待队列中移除,并继续执行后续代码。总结

CountdownLatch 是Java并发编程中一个非常实用的同步工具类,它通过计数器的方式实现了线程间的同步等待。其底层通过AQS的共享锁机制来实现计数器的同步操作,具有高效、灵活的特点。

通过本文的介绍,希望读者能够深入理解CountdownLatch的用法和底层原理,并在实际开发中灵活运用。

0 阅读:9

编程探索课程

简介:感谢大家的关注