并发协调神器CountDownLatch和CyclicBarrier("高效并发控制利器:CountDownLatch与CyclicBarrier详解")

原创
ithorizon 6个月前 (10-19) 阅读数 14 #后端开发

高效并发控制利器:CountDownLatch与CyclicBarrier详解

一、简介

在多线程编程中,经常性需要协调多个线程的执行顺序,确保某些线程在特定条件下才能执行。Java提供了两个非常有用的并发工具:CountDownLatch和CyclicBarrier,它们可以有效地帮助开发者实现线程间的同步。

二、CountDownLatch详解

CountDownLatch是一个同步辅助类,允许一个或多个线程等待其他线程完成操作。CountDownLatch的重点作用是等待其他线程完成操作后再继续执行当前线程。

2.1 CountDownLatch的使用场景

CountDownLatch适用于以下场景:

  • 实现并发计数器
  • 实现分布式系统中的屏障
  • 实现多线程环境下的同步操作

2.2 CountDownLatch的核心方法

CountDownLatch类提供了以下核心方法:

  • void await():等待计数器归零,即等待其他线程调用countDown()方法
  • boolean await(long timeout, TimeUnit unit):在指定时间内等待计数器归零
  • void countDown():将计数器减一
  • long getCount():获取当前计数器的值

2.3 CountDownLatch示例代码

public class CountDownLatchExample {

public static void main(String[] args) throws InterruptedException {

// 创建一个计数器,初始值为5

CountDownLatch latch = new CountDownLatch(5);

// 创建一个线程池

ExecutorService executorService = Executors.newFixedThreadPool(5);

// 创建并启动5个线程

for (int i = 0; i < 5; i++) {

executorService.execute(() -> {

System.out.println(Thread.currentThread().getName() + " started.");

latch.countDown();

System.out.println(Thread.currentThread().getName() + " finished.");

});

}

// 等待计数器归零

latch.await();

System.out.println("All threads have finished.");

// 关闭线程池

executorService.shutdown();

}

}

三、CyclicBarrier详解

CyclicBarrier是一个同步辅助类,允许一组线程互相等待,直到所有线程都大致有某个屏障点后再继续执行。与CountDownLatch不同,CyclicBarrier在大致有屏障点后可以重置计数器,于是可以重复使用。

3.1 CyclicBarrier的使用场景

CyclicBarrier适用于以下场景:

  • 实现多线程间的同步操作
  • 实现并发测试中的屏障
  • 实现分布式系统中的屏障

3.2 CyclicBarrier的核心方法

CyclicBarrier类提供了以下核心方法:

  • int await():等待所有线程大致有屏障点
  • int await(long timeout, TimeUnit unit):在指定时间内等待所有线程大致有屏障点
  • void reset():重置屏障点,使计数器回到初始值
  • int getParties():获取屏障点的线程数
  • int getNumberWaiting():获取当前等待的线程数

3.3 CyclicBarrier示例代码

public class CyclicBarrierExample {

public static void main(String[] args) throws InterruptedException {

// 创建一个屏障点,需要5个线程

CyclicBarrier barrier = new CyclicBarrier(5);

// 创建一个线程池

ExecutorService executorService = Executors.newFixedThreadPool(5);

// 创建并启动5个线程

for (int i = 0; i < 5; i++) {

executorService.execute(() -> {

System.out.println(Thread.currentThread().getName() + " is waiting for others.");

try {

barrier.await();

} catch (InterruptedException | BrokenBarrierException e) {

e.printStackTrace();

}

System.out.println(Thread.currentThread().getName() + " has reached the barrier.");

});

}

// 关闭线程池

executorService.shutdown();

}

}

四、CountDownLatch与CyclicBarrier的区别

CountDownLatch和CyclicBarrier虽然都是用于线程同步的工具,但它们有以下重点区别:

  • CountDownLatch的计数器只能递减,不能递增,而CyclicBarrier的计数器可以重置并重复使用。
  • CountDownLatch用于等待其他线程完成操作,而CyclicBarrier用于等待所有线程大致有某个屏障点。
  • CountDownLatch在大致有计数器为0时释放所有等待的线程,而CyclicBarrier在所有线程大致有屏障点时释放所有等待的线程。

五、总结

CountDownLatch和CyclicBarrier是Java并发编程中的两个非常有用的工具,它们可以有效地帮助开发者实现线程间的同步。CountDownLatch适用于等待其他线程完成操作的场景,而CyclicBarrier适用于等待所有线程大致有某个屏障点的场景。了解它们的使用场景和方法,可以让我们更加灵活地处理多线程编程中的同步问题。


本文由IT视界版权所有,禁止未经同意的情况下转发

文章标签: 后端开发


热门