在 Go 语言里,sync.WaitGroup
主要用于等待一组 goroutine 完成执行。在 Java 中,与之功能对应的实现方式有多种,下面为你详细介绍。
方式一:使用 CountDownLatch
CountDownLatch
是 Java 并发包 java.util.concurrent
里的一个同步工具类,它允许一个或多个线程等待其他线程完成操作。以下是示例代码:
java
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
包中的同步工具类,它能让一组线程在到达某个屏障(同步点)时相互等待。以下是示例代码:
java
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
更适合一组线程相互等待到达某个同步点的场景。你可以依据具体需求选择合适的工具类。