在 Go 语言里,sync.WaitGroup
主要用于等待一组 goroutine 完成执行。在 Java 中,与之功能对应的实现方式有多种,下面为你详细介绍。
方式一:使用 CountDownLatch
CountDownLatch
是 Java 并发包 java.util.concurrent
里的一个同步工具类,它允许一个或多个线程等待其他线程完成操作。以下是示例代码:
import java.util.concurrent.CountDownLatch;public class CountDownLatchExample {public static void main(String[] args) throws InterruptedException {int numThreads = 3;CountDownLatch latch = new CountDownLatch(numThreads);for (int i = 0; i < numThreads; i++) {final int threadId = i;new Thread(() -> {try {System.out.println("Thread " + threadId + " is working.");// 模拟工作Thread.sleep(1000); System.out.println("Thread " + threadId + " has finished.");} catch (InterruptedException e) {Thread.currentThread().interrupt();} finally {// 减少计数latch.countDown(); }}).start();}// 等待所有线程完成latch.await(); System.out.println("All threads have finished their work.");}
}
上述代码里,CountDownLatch
初始计数为 numThreads
,也就是线程的数量。每个线程完成工作后,会调用 countDown()
方法使计数减 1。主线程调用 await()
方法,会一直阻塞直到计数变为 0,这意味着所有线程都完成了工作。
方式二:使用 CyclicBarrier
CyclicBarrier
同样是 java.util.concurrent
包中的同步工具类,它能让一组线程在到达某个屏障(同步点)时相互等待。以下是示例代码:
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;public class CyclicBarrierExample {public static void main(String[] args) {int numThreads = 3;CyclicBarrier barrier = new CyclicBarrier(numThreads, () -> {System.out.println("All threads have reached the barrier.");});for (int i = 0; i < numThreads; i++) {final int threadId = i;new Thread(() -> {try {System.out.println("Thread " + threadId + " is working.");// 模拟工作Thread.sleep(1000); System.out.println("Thread " + threadId + " has reached the barrier.");// 等待其他线程到达屏障barrier.await(); } catch (InterruptedException | BrokenBarrierException e) {Thread.currentThread().interrupt();}}).start();}}
}
在这个例子中,CyclicBarrier
初始计数为 numThreads
。每个线程完成工作后,会调用 await()
方法等待其他线程。当所有线程都调用了 await()
方法,屏障就会被打破,并且可以执行一个可选的屏障操作。
综上所述,CountDownLatch
更适合一个或多个线程等待其他线程完成操作的场景,而 CyclicBarrier
更适合一组线程相互等待到达某个同步点的场景。你可以依据具体需求选择合适的工具类。