当前位置: 首页 > news >正文

构建一个简单的Java框架来测量并发执行任务的时间

文章目录

  • 一、完整代码
  • 二、代码解释
    • 1、方法签名
    • 2、初始化CountDownLatch
    • 3、提交任务到执行器
    • 4、任务线程的逻辑
    • 5、主线程的逻辑
    • 详细解释
    • 总结

以下代码实现了一个简单的框架,用于测量并发执行任务的时间。它使用了Executor来执行任务,并通过CountDownLatch来协调多个线程的执行。

假设我们使用一个简单的任务(如打印线程名称和任务编号),并运行这个方法。

一、完整代码

import java.util.concurrent.*;// Simple framework for timing concurrent execution
public static long time(Executor executor, int concurrency, Runnable action) throws InterruptedException {// 创建一个计数器,用于确保所有任务线程都已准备好CountDownLatch ready = new CountDownLatch(concurrency);// 创建一个计数器,用于通知所有任务线程开始执行CountDownLatch start = new CountDownLatch(1);// 创建一个计数器,用于确保所有任务线程都已完成CountDownLatch done = new CountDownLatch(concurrency);// 提交 concurrency 个任务到执行器for (int i = 0; i < concurrency; i++) {executor.execute(() -> {// 每个任务线程在开始执行前调用 countDown,表示已准备好ready.countDown(); // Tell timer we're readytry {// 每个任务线程等待 start 的计数器变为 0,即等待主线程通知开始执行start.await(); // Wait till peers are ready// 执行传入的 Runnable 任务action.run();} catch (InterruptedException e) {// 如果捕获到 InterruptedException,重新设置当前线程的中断状态Thread.currentThread().interrupt();} finally {// 每个任务线程执行完毕后,调用 countDown,表示已完成done.countDown(); // Tell timer we're done}});}// 主线程等待所有任务线程都准备好ready.await(); // Wait for all workers to be ready// 记录开始时间long startNanos = System.nanoTime();// 主线程通知所有任务线程开始执行start.countDown(); // And they're off!// 主线程等待所有任务线程都完成done.await(); // Wait for all workers to finish// 计算并返回任务执行的总时间(纳秒)return System.nanoTime() - startNanos;
}

为了更直观地理解这段代码的运行逻辑和输出效果,我们可以补充具体的输入参数,并展示完整的运行过程和最终输出。假设我们使用一个简单的任务(如打印线程名称和任务编号),并运行这个方法。

import java.util.concurrent.*;public class ConcurrentTimingFramework {// Simple framework for timing concurrent executionpublic static long time(Executor executor, int concurrency, Runnable action) throws InterruptedException {// 创建一个计数器,用于确保所有任务线程都已准备好CountDownLatch ready = new CountDownLatch(concurrency);// 创建一个计数器,用于通知所有任务线程开始执行CountDownLatch start = new CountDownLatch(1);// 创建一个计数器,用于确保所有任务线程都已完成CountDownLatch done = new CountDownLatch(concurrency);// 提交 concurrency 个任务到执行器for (int i = 0; i < concurrency; i++) {executor.execute(() -> {// 每个任务线程在开始执行前调用 countDown,表示已准备好ready.countDown(); // Tell timer we're readytry {// 每个任务线程等待 start 的计数器变为 0,即等待主线程通知开始执行start.await(); // Wait till peers are ready// 执行传入的 Runnable 任务action.run();} catch (InterruptedException e) {// 如果捕获到 InterruptedException,重新设置当前线程的中断状态Thread.currentThread().interrupt();} finally {// 每个任务线程执行完毕后,调用 countDown,表示已完成done.countDown(); // Tell timer we're done}});}// 主线程等待所有任务线程都准备好ready.await(); // Wait for all workers to be ready// 记录开始时间long startNanos = System.nanoTime();// 主线程通知所有任务线程开始执行start.countDown(); // And they're off!// 主线程等待所有任务线程都完成done.await(); // Wait for all workers to finish// 计算并返回任务执行的总时间(纳秒)return System.nanoTime() - startNanos;}public static void main(String[] args) throws InterruptedException {// 创建一个线程池,线程池大小为 4ExecutorService executor = Executors.newFixedThreadPool(4);// 定义并发级别int concurrency = 4;// 定义要执行的任务Runnable action = () -> {System.out.println("Task executed by " + Thread.currentThread().getName());};// 调用 time 方法,测量并发执行的时间long duration = time(executor, concurrency, action);// 打印执行时间System.out.println("Total execution time: " + duration + " nanoseconds");// 关闭线程池executor.shutdown();}
}

假设运行环境中有足够的线程资源,输出可能如下:

Task executed by pool-1-thread-1
Task executed by pool-1-thread-2
Task executed by pool-1-thread-3
Task executed by pool-1-thread-4
Total execution time: 1234567 nanoseconds

二、代码解释

1、方法签名

public static long time(Executor executor, int concurrency, Runnable action) throws InterruptedException {

参数:

  • Executor executor:一个执行器,用于执行任务。
  • int concurrency:并发级别,即同时运行的任务数量。
  • Runnable action:要执行的任务。
  • 返回值:long,表示任务执行的总时间(纳秒)。
  • 异常:throws InterruptedException,表示方法可能会抛出InterruptedException。

2、初始化CountDownLatch

CountDownLatch ready = new CountDownLatch(concurrency);
CountDownLatch start = new CountDownLatch(1);
CountDownLatch done = new CountDownLatch(concurrency);
  • ready:用于确保所有任务线程都已准备好。
  • start:用于通知所有任务线程开始执行。
  • done:用于确保所有任务线程都已完成。

3、提交任务到执行器

for (int i = 0; i < concurrency; i++) {executor.execute(() -> {
  • 提交concurrency个任务到executor。
  • 每个任务是一个Runnable,使用Lambda表达式实现。

4、任务线程的逻辑

ready.countDown(); // Tell timer we're ready
try {start.await(); // Wait till peers are readyaction.run();
} catch (InterruptedException e) {Thread.currentThread().interrupt();
} finally {done.countDown(); // Tell timer we're done
}
  • ready.countDown():每个任务线程在开始执行前调用countDown,表示已准备好。
  • start.await():任务线程等待start的计数器变为0,即等待主线程通知开始执行。
  • action.run():执行传入的Runnable任务。
  • catch (InterruptedException e):捕获InterruptedException,并重新设置当前线程的中断状态。
  • done.countDown():任务线程执行完毕后,调用countDown,表示已完成。

5、主线程的逻辑

ready.await(); // Wait for all workers to be ready
long startNanos = System.nanoTime();
start.countDown(); // And they're off!
done.await(); // Wait for all workers to finish
return System.nanoTime() - startNanos;
  • ready.await():主线程等待所有任务线程都准备好。
  • startNanos = System.nanoTime():记录开始时间。
  • start.countDown():主线程通知所有任务线程开始执行。
  • done.await():主线程等待所有任务线程都完成。
  • return System.nanoTime() - startNanos:计算并返回任务执行的总时间(纳秒)。

详细解释

  • 任务线程的准备阶段:
    每个任务线程调用ready.countDown(),表示已准备好。
    主线程调用ready.await(),等待所有任务线程准备好。
  • 任务线程的执行阶段:
    主线程调用start.countDown(),通知所有任务线程开始执行。
    每个任务线程调用start.await(),等待主线程的通知。
    任务线程执行action.run(),打印当前线程的名称。
  • 任务线程的完成阶段:
    每个任务线程调用done.countDown(),表示已完成。
    主线程调用done.await(),等待所有任务线程完成。
  • 计算执行时间:
    主线程记录任务开始时间和结束时间,计算总时间并返回。

总结

通过这个示例,我们可以看到time方法如何使用CountDownLatch来协调多个任务线程的执行,并测量任务的总执行时间。希望这个详细的解释和示例能帮助你更好地理解代码的运行逻辑和输出效果!

http://www.dtcms.com/a/289232.html

相关文章:

  • Linux安装jdk和maven教程
  • 论文解读:基于时域相干累积的UWB Radar 生命体征检测
  • PyTorch里的张量及张量的操作
  • The FastMCP Client
  • 反欺诈业务 Elasticsearch 分页与导出问题分析及解决方案
  • Kotlin函数式接口
  • 第六章 提炼:萃取本质--创建第二大脑读书笔记
  • 【esp32s3】4 - 从零开始入门 MQTT
  • Selenium 处理动态网页与等待机制详解
  • 谷歌开源项目MCP Toolbox for Databases实操:Docker一键部署与配置指南
  • zabbix服务器告警处理
  • 搜索文本2.6.2(从word、wps、excel、pdf和txt文件中查找文本的工具)
  • Web服务压力测试工具hey学习一:使用方法
  • seo优化
  • UE5多人MOBA+GAS 番外篇:移植Lyra的伤害特效(没用GameplayCue,因为我失败了┭┮﹏┭┮)
  • 均值漂移累积监测算法(MDAM):原理、命名、用途及实现
  • C++现代编程之旅:从基础语法到高性能应用开发
  • JavaScript 对象操作、继承与模块化实现
  • 深度学习图像分类数据集—八种贝类海鲜食物分类
  • UDP中的单播,多播,广播(代码实现)
  • #SVA语法滴水穿石# (014)关于链式蕴含的陷阱
  • python生成密钥
  • FreeSwitch编译部署
  • 去中心化协作智能生态系统
  • DataFrame数据的常用方法
  • LeetCode 刷题【8. 字符串转换整数 (atoi), 9. 回文数】
  • 国产HMC7044调试记录
  • 【Elasticsearch】合适的锅炒合适的菜:性能与成本平衡原理公式解析
  • 拓展面试题之-rabbitmq面试题
  • MySQL笔记3