欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 文旅 > 明星 > Java模拟并发请求,并统计请求的平均响应时间(CountDownLatch)

Java模拟并发请求,并统计请求的平均响应时间(CountDownLatch)

2025/5/6 22:11:55 来源:https://blog.csdn.net/ljy1998dsb/article/details/144409572  浏览:    关键词:Java模拟并发请求,并统计请求的平均响应时间(CountDownLatch)

 

背景

做实验过程中,想统计某个接口在并发请求的情况下的平均响应时间,如何用Java去实现这个功能呢?

技术实现


 一、可能遇到的问题


1、我们可以利用多线程去实现,只要多开几个线程,发起请求就好了,但是这不是真正的并发!因为线程的创建是有先后顺序的,这样做本质还是先创建的线程先执行。
2、操作系统对线程的调度我们是不知道的,我们该如何实现,主线程等待所有子线程执行完毕后,才去统计子线程耗时呢

这里就要用到Java中的CountDownLatch类。

二、什么是countDownlatch


CountDownLatch是一个同步工具类,它通过一个计数器来实现的,初始值为线程的数量。每当一个线程完成了自己的任务,计数器的值就相应得减1。当计数器到达0时,表示所有的线程都已执行完毕,然后在等待的线程就可以恢复执行任务。

关键方法:


countDown(): 每调用一次计数器值-1,直到count被减为0,代表所有线程全部执行完毕。
await(): 等待计数器变为0,即等待所有异步线程执行完毕。

二、利用countDownlatch实现多个线程同时启动


1、实现自定义任务线程

public class MyConcurrentThreadHcode implements Callable<Long> {private final CountDownLatch latch;private final CountDownLatch latchTotal;public MyConcurrentThreadHcode(CountDownLatch latch, CountDownLatch latchTotal) {this.latch = latch;this.latchTotal = latchTotal;}public Long call() {System.out.println(Thread.currentThread().getName()+",prepare at: "+System.currentTimeMillis());try {//先阻塞在这里,等待主线程将latch的计数器减为0latch.await();return doTask();} catch (InterruptedException e) {e.printStackTrace();} finally {//执行完一次latchTotal的计数器减一,latchTotal减到0后,主线程才会继续往下执行latchTotal.countDown();}return -1L;}public long doTask()  {Map<String, Object> params = new HashMap<String, Object>(7);params.put("minX", -68.8);params.put("maxX", -65);params.put("minY", 17);params.put("maxY", 20);params.put("startTimeStr", "2022-01-03T00:00:00");params.put("endTimeStr", "2022-01-03T10:00:00");long startTime = System.currentTimeMillis();String result = HttpUtil.get("http://localhost:6068/test/QueryByHCode", params);long endTime = System.currentTimeMillis();return endTime - startTime;}
}

2、主线程创建多线程,并同时启动

 public static void testConcurrentWCodeQuery(int totalThreadNum) throws ExecutionException, InterruptedException {//01 创建指定threadNum个数的线程CountDownLatch latchTotal = new CountDownLatch(totalThreadNum);CountDownLatch latch = new CountDownLatch(1);List<FutureTask> tasks = new ArrayList<>(totalThreadNum);for (int i = 0; i < totalThreadNum ; i++) {MyConcurrentThreadWcode task = new MyConcurrentThreadWcode(latch, latchTotal);FutureTask futureTask = new FutureTask(task);tasks.add(futureTask);Thread thread = new Thread(futureTask);thread.start();}//同时启动多个线程latch.countDown();try {/**所有子线程未执行完,主线程会阻塞在这里*/latchTotal.await();} catch (InterruptedException e) {e.printStackTrace();}long totalTime = 0L;int num = 0;for(FutureTask task : tasks){Long time = (Long)task.get();if(time > 0L){totalTime += time;num ++;}}System.out.println("查询平均耗时:" + totalTime/num + "ms");}

在主线程和任务线程中,创建了两个CountDownLatch变量,一个变量latch的初始计数器为1,变量latchTotal的初始计数器为线程数。

latch变量的作用是在主线程创建完所有子线程后,再启动子线程
latchTotal变量的作用是在子线程执行完所有任务后,在执行主线程代码

如此,便能实现多个线程同时启动,并在所有子线程执行完毕之后,统计其总耗时。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词