CountDownLatch,Semaphore,CyclicBarrier使用案例
2024-01-02 12:37:20
CountDownLatch是Java中的一个同步辅助工具类,它可以让一个或多个线程等待其他线程完成操作后再继续执行。CountDownLatch通过一个计数器来实现,计数器的初始值可以指定,当计数器的值变为0时,所有等待的线程就会被唤醒继续执行。
通常用于以下两种场景:一个线程等待多个其他线程执行完毕后再继续执行;?多个线程等待某个共同事件的发生后再继续执行。
CountDownLatch
??案例一
/**
* CountDownLatch使用案例,配合await()方法使用,线程执行完毕会阻塞在await()这,直至所有线程执行完毕
*/
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++) {
Thread thread = new Thread(new Worker(latch));
thread.start();
}
latch.await(); // 主线程等待所有子线程完成任务
System.out.println("All threads have completed their tasks. Main thread can continue.");
}
static class Worker implements Runnable {
private CountDownLatch latch;
public Worker(CountDownLatch latch) {
this.latch = latch;
}
@Override
public void run() {
try {
// 模拟子线程执行任务
Thread.sleep((long) (Math.random() * 1000));
System.out.println("Task completed by thread: " + Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
latch.countDown(); // 子线程完成任务后调用countDown减少计数器
}
}
}
}
输出结果:
Task completed by thread: Thread-2
Task completed by thread: Thread-0
Task completed by thread: Thread-1
All threads have completed their tasks. Main thread can continue.
?案例二
/**
* 使用CountDownLatch完成多个游戏玩家进度条的加载
* 直到所有玩家进度条加载完毕,游戏就可以启动了
*/
public class ProgressBarWithCountDownLatch {
public static void main(String[] args) throws InterruptedException {
int numThreads = 3;
CountDownLatch latch = new CountDownLatch(numThreads);
for (int i = 0; i < numThreads; i++) {
Thread thread = new Thread(new Task(latch, "Thread-" + i));
thread.start();
}
latch.await(); // 等待所有线程加载完毕
System.out.println("All progress bars have completed. Main thread can continue.");
}
static class Task implements Runnable {
private CountDownLatch latch;
private String threadName;
public Task(CountDownLatch latch, String threadName) {
this.latch = latch;
this.threadName = threadName;
}
@Override
public void run() {
System.out.println("Thread " + threadName + " started loading progress bar");
for (int i = 0; i <= 100; i += 10) {
updateProgressBar(threadName, i);
try {
Thread.sleep((long) (20 * Math.random())); // 模拟加载进度
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("Thread " + threadName + " finished loading progress bar");
latch.countDown(); // 减少计数器
}
static void updateProgressBar(String threadName, int progress) {
// 更新进度条的显示
System.out.println("Thread " + threadName + " - Progress: " + progress + "%");
}
}
}
输出结果
Thread Thread-0 started loading progress bar
Thread Thread-2 started loading progress bar
Thread Thread-2 - Progress: 0%
Thread Thread-1 started loading progress bar
Thread Thread-0 - Progress: 0%
Thread Thread-1 - Progress: 0%
Thread Thread-2 - Progress: 10%
Thread Thread-2 - Progress: 20%
Thread Thread-0 - Progress: 10%
Thread Thread-1 - Progress: 10%
Thread Thread-2 - Progress: 30%
Thread Thread-1 - Progress: 20%
Thread Thread-0 - Progress: 20%
Thread Thread-1 - Progress: 30%
Thread Thread-1 - Progress: 40%
Thread Thread-2 - Progress: 40%
Thread Thread-0 - Progress: 30%
Thread Thread-2 - Progress: 50%
Thread Thread-0 - Progress: 40%
Thread Thread-0 - Progress: 50%
Thread Thread-1 - Progress: 50%
Thread Thread-1 - Progress: 60%
Thread Thread-2 - Progress: 60%
Thread Thread-2 - Progress: 70%
Thread Thread-0 - Progress: 60%
Thread Thread-0 - Progress: 70%
Thread Thread-1 - Progress: 70%
Thread Thread-1 - Progress: 80%
Thread Thread-2 - Progress: 80%
Thread Thread-2 - Progress: 90%
Thread Thread-0 - Progress: 80%
Thread Thread-2 - Progress: 100%
Thread Thread-0 - Progress: 90%
Thread Thread-1 - Progress: 90%
Thread Thread-2 finished loading progress bar
Thread Thread-0 - Progress: 100%
Thread Thread-1 - Progress: 100%
Thread Thread-0 finished loading progress bar
Thread Thread-1 finished loading progress bar
All progress bars have completed. Main thread can continue.
Process finished with exit code 0
Semaphore
Semaphore是Java中的一个同步工具类,它可以控制同时访问特定资源的线程数量。Semaphore维护了一组许可,线程可以通过acquire()方法获取许可,通过release()方法释放许可。当许可数达到上限时,后续请求许可的线程会被阻塞,直到有其他线程释放许可。 Semaphore通常用于以下场景: 控制同时访问的线程数量,如连接池、资源池等;限流,控制系统的并发访问量。
?案例一:使用acquire()
/**
* Semaphore使用案例
* 一开始设置了semaphore = 2, 即最大同时存在的线程为2
* 在本次案例中我们开启了5个线程,执行任务
* 每次使用需要调用acquire()方法,如果获取成功,semaphore-1,然后往下执行;执行完毕semaphore+1
* 否则会阻塞,直到有其他线程释放了semaphore
*/
public class SemaphoreExample {
public static void main(String[] args) {
Semaphore semaphore = new Semaphore(2); // 允许同时访问打印机的线程数量为2
for (int i = 1; i <= 5; i++) {
new Thread(() -> {
try {
System.out.println(LocalDateTime.now().format(DateTimeFormatter.ofPattern("hh:mm:ss")) + " " + Thread.currentThread().getName() + " is waiting to access the printer");
semaphore.acquire(); // 获取许可
System.out.println(LocalDateTime.now().format(DateTimeFormatter.ofPattern("hh:mm:ss")) + " " + Thread.currentThread().getName() + " is printing");
Thread.sleep(2000); // 假设打印需要2秒钟
System.out.println(LocalDateTime.now().format(DateTimeFormatter.ofPattern("hh:mm:ss")) + " " + Thread.currentThread().getName() + " has finished printing");
semaphore.release(); // 释放许可
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start(); // 有5个线程想要访问打印机
}
}
}
输出结果
11:30:46 Thread-1 is waiting to access the printer
11:30:46 Thread-2 is waiting to access the printer
11:30:46 Thread-4 is waiting to access the printer
11:30:46 Thread-1 is printing
11:30:46 Thread-0 is waiting to access the printer
11:30:46 Thread-3 is waiting to access the printer
11:30:46 Thread-2 is printing
11:30:48 Thread-1 has finished printing
11:30:48 Thread-2 has finished printing
11:30:48 Thread-4 is printing
11:30:48 Thread-0 is printing
11:30:50 Thread-0 has finished printing
11:30:50 Thread-4 has finished printing
11:30:50 Thread-3 is printing
11:30:52 Thread-3 has finished printing
Process finished with exit code 0
案例二:使用tryAcquire()
/**
* Semaphore使用tryacquire()方法,如果没有semaphore,则会直接返回false,而不会被阻塞,等待其他线程释放资源
*
*/
public class SemaphoreExampleTryAcquire {
public static void main(String[] args) {
Semaphore semaphore = new Semaphore(2); // 允许同时访问打印机的线程数量为2
for (int i = 0; i < 5; i++) {
new Thread(() -> {
if (semaphore.tryAcquire()) {
try {
System.out.println(LocalDateTime.now().format(DateTimeFormatter.ofPattern("hh:mm:ss")) + " " + Thread.currentThread().getName() + " is printing");
Thread.sleep(2000); // 假设打印需要2秒钟
System.out.println(LocalDateTime.now().format(DateTimeFormatter.ofPattern("hh:mm:ss")) + " " + Thread.currentThread().getName() + " has finished printing");
semaphore.release(); // 释放许可
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
System.out.println(LocalDateTime.now().format(DateTimeFormatter.ofPattern("hh:mm:ss")) + " " + Thread.currentThread().getName() + " failed to acquire the semaphore");
}
}).start(); // 有5个线程想要访问打印机
}
}
}
输出结果
11:32:58 Thread-4 failed to acquire the semaphore
11:32:58 Thread-2 failed to acquire the semaphore
11:32:58 Thread-3 failed to acquire the semaphore
11:32:58 Thread-0 is printing
11:32:58 Thread-1 is printing
11:33:00 Thread-0 has finished printing
11:33:00 Thread-1 has finished printing
Process finished with exit code 0
CyclicBarrier使用案例
CyclicBarrier是Java中的一个同步辅助工具类,它允许一组线程互相等待,直到所有线程都达到某个公共屏障点,然后再继续执行。CyclicBarrier的特点是可以循环使用,一旦所有线程都到达屏障点,屏障就会打开,所有线程会被释放,并且CyclicBarrier可以被重置以再次使用。 CyclicBarrier通常用于以下场景: 将多个线程分成多个阶段执行,每个阶段的线程都必须等待其他线程完成后才能继续执行。 同时开始执行多个任务,等所有任务都准备好后再开始执行。
/**
* CyclicBarrier使用案例,线程执行任务完成后会停留在await(),
* 直到所有线程执行任务完毕,才会被放行;
* 接着就会继续执行其他的任务
*/
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. Starting the next phase.");
});
for (int i = 0; i < numThreads; i++) {
Thread worker = new Thread(new Worker(barrier, "Worker-" + i));
worker.start();
}
}
static class Worker implements Runnable {
private CyclicBarrier barrier;
private String workerName;
public Worker(CyclicBarrier barrier, String workerName) {
this.barrier = barrier;
this.workerName = workerName;
}
@Override
public void run() {
System.out.println(LocalDateTime.now().format(DateTimeFormatter.ofPattern("hh:mm:ss")) + " Worker " + workerName + " is working");
try {
Thread.sleep((long) (Math.random() * 2000)); // 模拟不同的工作时间
System.out.println(LocalDateTime.now().format(DateTimeFormatter.ofPattern("hh:mm:ss")) + " Worker " + workerName + " has reached the barrier");
barrier.await(); // 等待所有线程到达屏障
System.out.println(LocalDateTime.now().format(DateTimeFormatter.ofPattern("hh:mm:ss")) + " Worker " + workerName + " is continuing to work");
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
}
}
}
输出结果
12:45:40 Worker Worker-1 is working
12:45:40 Worker Worker-2 is working
12:45:40 Worker Worker-0 is working
12:45:40 Worker Worker-0 has reached the barrier
12:45:40 Worker Worker-1 has reached the barrier
12:45:42 Worker Worker-2 has reached the barrier
All threads have reached the barrier. Starting the next phase.
12:45:42 Worker Worker-2 is continuing to work
12:45:42 Worker Worker-0 is continuing to work
12:45:42 Worker Worker-1 is continuing to work
Process finished with exit code 0
总结
总的来说,CountDownLatch用于等待其他线程的完成,Semaphore用于控制并发线程数量,CyclicBarrier用于多阶段任务的协作。
文章来源:https://blog.csdn.net/xuan__xia/article/details/135337730
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!