CountDownLatch、CyclicBarrier、Semaphore等并发工具类实际应用场景
发布时间: 2024-02-12 12:41:37 阅读量: 50 订阅数: 22
# 1. 引言
## 1.1 介绍CountDownLatch、CyclicBarrier、Semaphore等并发工具类
在多线程编程中,为了实现线程间的协作和资源的合理利用,我们经常会用到一些并发工具类,比如CountDownLatch、CyclicBarrier和Semaphore等。这些工具类提供了丰富的功能,能够帮助我们更加高效地实现多线程任务的协同和资源的管理。
## 1.2 重要性和优势
使用并发工具类能够帮助我们简化多线程编程中的复杂操作,提高程序的并发性能和可维护性。这些工具类可以有效地实现线程间的协作和资源的共享,避免死锁和资源竞争等问题,同时也能更好地利用多核处理器的性能优势。
接下来,我们将分别介绍CountDownLatch、CyclicBarrier和Semaphore的实际应用场景,以及它们的具体用法和优势。
# 2. CountDownLatch的实际应用场景
CountDownLatch是一种在多线程环境下协调线程之间操作的工具类。它的主要作用是让一个或多个线程等待其他线程完成一系列操作后再继续执行。下面我们将详细介绍CountDownLatch的两个实际应用场景。
### 2.1 启动并发任务前的等待
在某些场景下,我们需要在主线程等待所有并发任务执行完成后再继续执行。这时可以使用CountDownLatch来实现。
```java
import java.util.concurrent.CountDownLatch;
public class CountDownLatchDemo {
private static final int TASK_COUNT = 5;
public static void main(String[] args) throws InterruptedException {
CountDownLatch latch = new CountDownLatch(TASK_COUNT);
for (int i = 0; i < TASK_COUNT; i++) {
Thread thread = new Thread(new Task(latch));
thread.start();
}
// 主线程等待所有任务完成
latch.await();
System.out.println("All tasks have finished. Continue the main thread.");
}
static class Task implements Runnable {
private CountDownLatch latch;
public Task(CountDownLatch latch) {
this.latch = latch;
}
@Override
public void run() {
// 执行任务
System.out.println("Executing task...");
// 完成任务后计数器减一
latch.countDown();
}
}
}
```
上述代码中,我们创建了一个CountDownLatch对象,并指定初始计数器值为5。然后在主线程中创建了5个子线程,每个子线程执行一个任务。在每个子线程执行完任务后,通过`latch.countDown()`操作将计数器减一。主线程使用`latch.await()`方法等待计数器变为0,然后继续执行。
运行以上示例代码,可以看到主线程在所有任务完成后输出"All tasks have finished. Continue the main thread."。
### 2.2 多线程任务的协作与同步
CountDownLatch还可用于多个线程之间的协作与同步。比如我们有一个任务需要分成三个阶段完成,每个阶段都可以由多个线程并发执行,但当前阶段的线程必须等待其他线程完成才能继续执行。
```java
import java.util.concurrent.CountDownLatch;
public class CountDownLatchDemo {
private static final int THREAD_COUNT = 3;
private static final int PHASE_COUNT = 3;
public static void main(String[] args) throws InterruptedException {
CountDownLatch phaseLatch = new CountDownLatch(PHASE_COUNT);
CountDownLatch threadLatch = new CountDownLatch(THREAD_COUNT);
for (int i = 0; i < THREAD_COUNT; i++) {
Thread thread = new Thread(new Task(phaseLatch, threadLatch));
thread.start();
}
for (int phase = 0; phase < PHASE_COUNT; phase++) {
// 主线程等待当前阶段的任务完成
phaseLatch.await();
System.out.println("Phase " + phase + " has finished.");
// 重置计数器
phaseLatch = new CountDownLatch(PHASE_COUNT);
}
// 主线程等待所有任务完成
threadLatch.await();
System.out.println("All tasks have finished. Continue the main thread.");
}
static class Task implements Runnable {
private CountDownLatch phaseLatch;
private CountDownLatch threadLatch;
public Task(CountDownLatch phaseLatch, CountDownLatch threadLatch) {
this.phaseLatch = phaseLatch;
this.threadLatch = threadLatch;
}
@Override
public void run() {
for (int phase = 0; phase < PHASE_COUNT; phase++) {
// 执行当前阶段的任务
System.out.println("Thread " + Thread.currentThread().getId() + " is executing phase " + phase);
// 完成当前阶段的任务后计数器减一
phaseLatch.countDown();
try {
// 等待其他线程完成当前阶段的任务
phaseLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// 所有阶段的任务完成后计数器减一
threadLatch.countDown();
}
}
}
```
上述代码中,我们使用了两个CountDownLatch对象。`phaseLatch`对象用于控制多个线程之间同步执行每个阶段的任务,`threadLatch`对象用于主线程等待所有任务完成。每个线程循环执行三个阶段的任务,使用计数器控制线程之间的同步,通过`phaseLatch.countDown()`来减少阶段计数器,通过`phaseLatch.await()`来等待其他线程完成当前阶段的任务。
运行以上代码,可以看到每个线程在不同阶段的任务执行中协作与同步,最终主线程在所有任务完成后继续执行。
# 3. CyclicBarrier的实际应用场景
CyclicBarrier是一种同步辅助类,它允许一组线程在某个点上相互等待,直到达到某个共同的障碍点。与CountDownLatch不同的是,CyclicBarrier可以被重置并再次使用,它适用于需要分阶段协作的场景。
#### 3.1 多线程任务的阶段性协作
在某些情况下,我们需要将一个大的任务拆分为多个小的子任务,并发执行这些子任务,然后在每个阶段结束后进行合并,最终得到最终的结果。
例如,假设我们需要处理一个包含1亿个元素的列表,可以将列表分割为多个子列表,并让多个线程并发处理这些子列表。在每个子列表处理完毕后,线程需要等待其他线程完成,然后将结果合并成最终的结果。
下面是一个使用CyclicBarrier来实现多线程任务的阶段性协作的示例代码:
```java
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
public class MultiThreadTask {
private static final int THREAD_COUNT = 5;
private static final int LIST_SIZE = 10000000;
public static void main(String[] args) {
List<Integer> list = generateList(LIST_SIZE);
CyclicBarrier barrier = new CyclicBarrier(THREAD_COUNT, () -> {
// 所有子任务完成后执行的合并逻辑
int sum = 0;
for (int i = 0; i < THREAD_COUNT; i++) {
sum += ResultHolder.getInstance().getResult(i);
}
System.out.printl
```
0
0