小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
CountDownLatch
直译过来是倒计时门闩,其两个典型用法要么为一等多,要么为多等一,这里一一演示这两种用法,需要注意 CountDownLatch
不能重用,如果需要重用可以考虑使用CyclicBarrier
用法 1(一等多)
一个线程等待多个线程都执行完毕,再继续执行自己的工作
package org.example.concurrent;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* 本类用于演示 CountDownLatch 的一个用法
* 一个线程等待其他线程都完成后继续进行后续的工作
* 这里假设主线程需要等待 5 个子线程都完成检查后再进行到下一个阶段
*
* @author Catch
*/
public class CountDownLatchUsage1 {
public static void main(String[] args) throws InterruptedException {
CountDownLatch latch=new CountDownLatch(5);
ExecutorService executorService = Executors.newFixedThreadPool(5);
for (int i = 0; i < 5; i++) {
int no=i+1;
Runnable r=()->{
try {
Thread.sleep((long) (Math.random()*10000));
System.out.println("No."+no+"完成了检查工作");
} catch (InterruptedException e) {
e.printStackTrace();
}finally{
latch.countDown();
}
};
executorService.submit(r);
}
System.out.println("等待 5 个子线程完成检查工作...");
latch.await();
System.out.println("所有子线程都完成了检查工作, 开始进入下一个阶段.");
}
}
复制代码
用法 2(多等一)
下面是多个线程等待一个线程完成工作,然后多个线程同时开始工作
package org.example.concurrent;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* 本类用于演示 CountDownLatch 的一个用法
* 多个线程等待一个线程完成工作,然后多个线程同时开始工作
* 这里假设我们要进行一次压测, 首先准备 1000 个线程,
* 当 1000 个线程都准备完毕后同时发起请求,来达到模拟高峰期用户访问的效果
*
* @author Catch
*/
public class CountDownLatchUsage2 {
public static void main(String[] args) throws InterruptedException {
CountDownLatch begin=new CountDownLatch(1);
CountDownLatch end = new CountDownLatch(1000);
ExecutorService executorService = Executors.newFixedThreadPool(1000);
for (int i = 0; i < 1000; i++) {
Runnable r=()->{
try {
// 可以在 begin.await() 前进行一些准备或初始化工作
begin.await();
// 模拟压测耗时, 有的快有的慢
Thread.sleep((long) (Math.random() * 5000));
System.out.println(Thread.currentThread().getName()+"发起请求...");
} catch (InterruptedException e) {
e.printStackTrace();
}finally{
end.countDown();
}
};
executorService.submit(r);
}
Thread.sleep(3000);
System.out.println("所有线程已准备完毕, 压测开始!");
begin.countDown();
end.await();
System.out.println("所有线程都请求完毕, 压测结束!");
}
}
复制代码
近期评论