返回
多线程并发的世界里,如何优雅的协调工作
后端
2024-02-03 07:25:59
CountDownLatch:减少计数
概述
CountDownLatch是一个同步工具,它允许一个或多个线程等待其他线程完成工作。它有一个计数器,当计数器减到0时,所有等待的线程都会被唤醒。
使用场景
CountDownLatch通常用于以下场景:
- 主线程等待所有子线程完成任务后继续执行。
- 一个线程等待多个线程完成任务后继续执行。
- 多个线程等待一个共享资源可用后继续执行。
示例
以下是一个使用CountDownLatch的示例:
public class CountDownLatchDemo {
public static void main(String[] args) {
// 创建一个CountDownLatch,计数器为3
CountDownLatch latch = new CountDownLatch(3);
// 创建3个线程,每个线程都调用countDown()方法来减少计数器
for (int i = 0; i < 3; i++) {
new Thread(() -> {
System.out.println("子线程" + Thread.currentThread().getName() + "开始执行");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
latch.countDown();
System.out.println("子线程" + Thread.currentThread().getName() + "执行结束");
}).start();
}
// 主线程等待CountDownLatch的计数器减到0
try {
latch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
// 所有子线程执行结束,主线程继续执行
System.out.println("主线程执行结束");
}
}
输出结果:
子线程Thread-0开始执行
子线程Thread-1开始执行
子线程Thread-2开始执行
子线程Thread-0执行结束
子线程Thread-1执行结束
子线程Thread-2执行结束
主线程执行结束
CyclicBarrier:循环屏障
概述
CyclicBarrier是一个同步工具,它允许一组线程等待直到所有线程都到达一个公共屏障点。当所有线程都到达屏障点时,屏障将被解除,所有线程将继续执行。
使用场景
CyclicBarrier通常用于以下场景:
- 多个线程需要在同一时间执行某个任务。
- 多个线程需要在完成某个任务后继续执行。
示例
以下是一个使用CyclicBarrier的示例:
public class CyclicBarrierDemo {
public static void main(String[] args) {
// 创建一个CyclicBarrier,屏障点为3
CyclicBarrier barrier = new CyclicBarrier(3);
// 创建3个线程,每个线程都调用await()方法来等待其他线程到达屏障点
for (int i = 0; i < 3; i++) {
new Thread(() -> {
System.out.println("子线程" + Thread.currentThread().getName() + "开始执行");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
barrier.await();
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
System.out.println("子线程" + Thread.currentThread().getName() + "执行结束");
}).start();
}
// 所有子线程到达屏障点,屏障解除,所有线程继续执行
System.out.println("主线程执行结束");
}
}
输出结果:
子线程Thread-0开始执行
子线程Thread-1开始执行
子线程Thread-2开始执行
子线程Thread-0执行结束
子线程Thread-1执行结束
子线程Thread-2执行结束
主线程执行结束
Semaphore:信号量
概述
Semaphore是一个同步工具,它允许多个线程并发访问共享资源,但对访问共享资源的线程数量进行限制。
使用场景
Semaphore通常用于以下场景:
- 控制对共享资源的访问。
- 限制同时访问共享资源的线程数量。
示例
以下是一个使用Semaphore的示例:
public class SemaphoreDemo {
public static void main(String[] args) {
// 创建一个Semaphore,许可证数量为3
Semaphore semaphore = new Semaphore(3);
// 创建10个线程,每个线程都尝试获取许可证来访问共享资源
for (int i = 0; i < 10; i++) {
new Thread(() -> {
try {
// 获取许可证
semaphore.acquire();
System.out.println("子线程" + Thread.currentThread().getName() + "获取许可证,开始访问共享资源");
Thread.sleep(1000);
// 释放许可证
semaphore.release();
System.out.println("子线程" + Thread.currentThread().getName() + "释放许可证,结束访问共享资源");
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
}
// 主线程等待所有子线程执行结束
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 所有子线程执行结束,主线程继续执行
System.out.println("主线程执行结束");
}
}
输出结果:
子线程Thread-0获取许可证,开始访问共享资源
子线程Thread-1获取许可证,开始访问共享资源
子线程Thread-2获取许可证,开始访问共享资源
子线程Thread-0释放许可证,结束访问共享资源
子线程Thread-3获取许可证,开始访问共享资源
子线程Thread-1释放许可证,结束访问共享资源
子线程Thread-4获取许可证,开始访问共享资源
子线程Thread-2释放许可证,结束访问共享资源
子线程Thread-5获取许可证,开始访问共享资源
子线程Thread-3释放许可证,结束访问共享资源
子线程Thread-6获取许可证,开始访问共享资源
子线程Thread-4释放许可证,结束访问共享资源
子线程Thread-7获取许可证,开始访问共享资源
子线程Thread-5释放许可证,结束访问共享资源
子线程Thread-8获取许可证,开始访问共享资源
子线程Thread-6释放许可证,结束访问共享资源
子线程Thread-9获取许可证,开始访问共享资源
子线程Thread-7释放许可证,结束访问共享资源
子线程Thread-8释放许可证,结束访问共享资源
子线程Thread-9释放许可证,结束访问共享资源
主线程执行结束