在Java的并发编程中,`CountDownLatch`和`CyclicBarrier`是两个非常重要的工具类,它们提供了便捷的线程同步机制,能够帮助开发者更好地管理并发任务。本文将详细介绍这两个工具类的应用与原理。
`CountDownLatch`允许一个或多个线程等待其他线程完成一组操作。它通常用于以下场景:
`CountDownLatch`通过一个计数器来跟踪尚未完成的任务数量。调用`await()`方法的线程会被阻塞,直到计数器减至零。每次调用`countDown()`方法时,计数器减一。当计数器变为零时,所有等待的线程会被唤醒并继续执行。
CountDownLatch latch = new CountDownLatch(3);
Runnable task = () -> {
try {
// 模拟任务执行
Thread.sleep((long) (Math.random() * 10000));
System.out.println(Thread.currentThread().getName() + " 完成");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
latch.countDown();
}
};
for (int i = 0; i < 3; i++) {
new Thread(task).start();
}
try {
latch.await();
System.out.println("所有任务完成");
} catch (InterruptedException e) {
e.printStackTrace();
}
`CyclicBarrier`允许一组线程互相等待,直到所有线程都到达一个共同的屏障点。它通常用于以下场景:
`CyclicBarrier`将一组线程放在屏障上,所有线程调用`await()`方法,直到最后一个线程也调用了`await()`方法。此时,可以选择一个屏障动作(BarrierAction)在所有线程都被释放之前执行。如果某个线程在到达屏障时被中断或超时,则所有等待的线程会被中断或返回一个特殊的超时状态。
int parties = 3;
CyclicBarrier barrier = new CyclicBarrier(parties, () -> {
System.out.println("所有线程都到达屏障点,执行屏障动作");
});
Runnable task = () -> {
try {
// 模拟任务执行
Thread.sleep((long) (Math.random() * 10000));
System.out.println(Thread.currentThread().getName() + " 准备到达屏障点");
barrier.await();
System.out.println(Thread.currentThread().getName() + " 已经通过屏障点");
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
};
for (int i = 0; i < parties; i++) {
new Thread(task).start();
}
`CountDownLatch`和`CyclicBarrier`是Java并发编程中非常有用的工具类。`CountDownLatch`适用于一次性任务等待场景,而`CyclicBarrier`则适用于周期性任务等待场景。通过合理使用这两个工具类,开发者可以更高效地管理并发任务,提高程序的性能和可靠性。