构建一个简单的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.pswp.cn/web/89817.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/89817.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

精通 triton 使用 MLIR 的源码逻辑 - 第001节:triton 的应用简介

项目使用到 MLIR&#xff0c;通过了解 triton 对 MLIR 的使用&#xff0c;体会到 MLIR 在较大项目中的使用方式&#xff0c;汇总一下。1. Triton 概述OpenAI Triton 是一个开源的编程语言和编译器&#xff0c;旨在简化 GPU 高性能计算&#xff08;HPC&#xff09; 的开发&#…

Python爬虫-政务网站自动采集数据框架

前言 本文是该专栏的第81篇,后面会持续分享python爬虫干货知识,记得关注。 本文,笔者将详细介绍一个基于政务网站进行自动采集数据的爬虫框架。对此感兴趣的同学,千万别错过。 废话不多说,具体细节部分以及详细思路逻辑,跟着笔者直接往下看正文部分。(附带框架完整代码…

GitHub 趋势日报 (2025年07月19日)

&#x1f4ca; 由 TrendForge 系统生成 | &#x1f310; https://trendforge.devlive.org/ &#x1f310; 本日报中的项目描述已自动翻译为中文 &#x1f4c8; 今日获星趋势图 今日获星趋势图1054shadPS4695n8n361remote-jobs321maigret257github-mcp-server249open_deep_res…

2025开源组件安全工具推荐OpenSCA

OpenSCA是国内最早的开源SCA平台&#xff0c;继承了商业级SCA的开源应用安全缺陷检测、多级开源依赖挖掘、纵深代码同源检测等核心能力&#xff0c;通过软件成分分析、依赖分析、特征分析、引用识别、合规分析等方法&#xff0c;深度挖掘组件中潜藏的各类安全漏洞及开源协议风险…

旅游管理实训基地建设:筑牢文旅人才培养的实践基石

随着文旅产业的蓬勃发展&#xff0c;行业对高素质、强实践的旅游管理人才需求日益迫切。旅游管理实训基地建设作为连接理论教学与行业实践的关键纽带&#xff0c;既是深化产教融合的重要载体&#xff0c;也是提升旅游管理专业人才培养质量的核心抓手。一、旅游管理实训基地建设…

网络爬虫的相关知识和操作

介绍 爬虫的定义 爬虫&#xff08;Web Crawler&#xff09;是一种自动化程序&#xff0c;用于从互联网上抓取、提取和存储网页数据。其核心功能是模拟人类浏览行为&#xff0c;访问目标网站并解析页面内容&#xff0c;最终将结构化数据保存到本地或数据库。 爬虫的工作原理 …

【vue-6】Vue3 响应式数据声明:深入理解 ref()

在 Vue3 的 Composition API 中&#xff0c;ref() 是最基础也是最常用的响应式数据声明方式之一。它为开发者提供了一种简单而强大的方式来管理组件状态。本文将深入探讨 ref() 的工作原理、使用场景以及最佳实践。 1. 什么是 ref()&#xff1f; ref() 是 Vue3 提供的一个函数&…

HTML常用标签汇总(精简版)

<!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>简单标记</title> </head><body>&…

【.net core】支持通过属性名称索引的泛型包装类

类/// <summary> /// 支持通过属性名称索引的泛型包装类 /// </summary> public class PropertyIndexer<T> : IEnumerable<T> {private T[] _items;private T _instance;private PropertyInfo[] _properties;private bool _caseSensitive;public Prope…

【机器学习|学习笔记】详解支持向量机(Support Vector Machine,SVM)为何要引入核函数?为何对缺失数据敏感?

【机器学习|学习笔记】详解支持向量机(Support Vector Machine,SVM)为何要引入核函数?为何对缺失数据敏感? 【机器学习|学习笔记】详解支持向量机(Support Vector Machine,SVM)为何要引入核函数?为何对缺失数据敏感? 文章目录 【机器学习|学习笔记】详解支持向量机(…

Bicep入门篇

前言 Azure Bicep 是 ARM 模板的最新版本,旨在解决开发人员在将资源部署到 Azure 时遇到的一些问题。它是一款开源工具,实际上是一种领域特定语言 (DSL),它提供了一种声明式编写基础架构的方法,该基础架构描述了虚拟机、Web 应用和网络接口等云资源的拓扑结构。它还鼓励在…

命名实体识别15年研究全景:从规则到机器学习的演进(1991-2006)

本文精读NRC Canada与NYU联合发表的经典综述《A survey of named entity recognition and classification》&#xff0c;解析NERC技术演进脉络与核心方法论 一、为什么命名实体识别&#xff08;NER&#xff09;如此重要&#xff1f; 命名实体识别&#xff08;Named Entity Rec…

eNSP综合实验(DNCP、NAT、TELET、HTTP、DNS)

1搭建实验拓扑2实验目的学习掌握eNSP中的命令3实验步骤3.1配置连接PC和客户端的交换机(仅以右侧为例)[Huawei]vlan batch 10 20 #创建vlan Info: This operation may take a few seconds. Please wait for a moment...done. [Huawei]un in en [Huawei]interface e0/0/2 [Huawei…

无人系统与安防监控中的超低延迟直播技术应用:基于大牛直播SDK的实战分享

技术背景 在 无人机、机器人 以及 智能安防 等高要求行业&#xff0c;高清视频的超低延迟传输 正在成为影响系统性能与业务决策的重要因素。无论是工业生产线的远程巡检、突发事件的应急响应&#xff0c;还是高风险环境下的智能监控与远程控制&#xff0c;视频链路的传输延迟都…

go语言学习之包

概念&#xff1a;在Go 语言中&#xff0c;包由一个或多个保存在同一目录的源码文件组成&#xff0c;包名宇目录名无关&#xff0c;但是通常大家习惯包名和目录名保持一致&#xff0c;同一目录的源码文件必须使用相同的包名。包的用途类似于其他语言的命名空间&#xff0c;可以限…

pytorch学习笔记(五)-- 计算机视觉的迁移学习

系列文章目录 pytorch学习笔记&#xff08;一&#xff09;-- pytorch深度学习框架基本知识了解 pytorch学习笔记&#xff08;二&#xff09;-- pytorch模型开发步骤详解 pytorch学习笔记&#xff08;三&#xff09;-- TensorBoard的介绍 pytorch学习笔记&#xff08;四&…

数字IC后端培训教程之数字后端项目典型项目案例解析

数字IC后端低功耗设计实现案例分享(3个power domain&#xff0c;2个voltage domain) Q1: 电路如下图&#xff0c;clk是一个很慢的时钟test_clk&#xff08;属于DFT的)&#xff0c;DFF1与and 形成一个clock gating check。跑pr 发现&#xff0c;时钟树综合CTS阶段&#xff08;C…

2025 Data Whale x PyTorch 安装学习笔记(Windows 版)

一、Anaconda 的安装与基本操作 1. 安装 Anaconda/miniconda 官方链接&#xff1a;Anaconda | Individual Edition 根据系统版本选择合适的安装包下载并安装。 2. 检验安装 打开 “开始” 菜单&#xff0c;找到 “Anaconda Prompt”&#xff08;一般在 Anaconda3 文件夹…

mac OS上docker安装zookeeper

拉取镜像&#xff1a;$ docker pull zookeeper:3.5.7 3.5.7: Pulling from library/zookeeper 3.5.7: Pulling from library/zookeeper 3.5.7: Pulling from library/zookeeper no matching manifest for linux/arm64/v8 in the manifest list entries报错&#xff1a;由于时M3…

设备通过4G网卡接入EasyCVR视频融合平台,出现无法播放的问题排查和解决

EasyCVR视频融合平台作为支持多协议接入、多设备集中管理的综合性视频解决方案&#xff0c;可实现各类终端设备的视频流汇聚与实时播放。近期收到用户反馈&#xff0c;在EasyCVR平台接入设备后出现视频流无法播放的情况。为帮助更多用户快速排查同类问题&#xff0c;现将具体处…