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

文章目录

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

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

一、完整代码

java 复制代码
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 ready
            try {
                // 每个任务线程等待 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;
}

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

java 复制代码
import java.util.concurrent.*;

public class ConcurrentTimingFramework {

    // 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 ready
                try {
                    // 每个任务线程等待 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 {
        // 创建一个线程池,线程池大小为 4
        ExecutorService 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();
    }
}

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

java 复制代码
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、方法签名

java 复制代码
public static long time(Executor executor, int concurrency, Runnable action) throws InterruptedException {

参数:

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

2、初始化CountDownLatch

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

3、提交任务到执行器

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

4、任务线程的逻辑

java 复制代码
ready.countDown(); // Tell timer we're ready
try {
    start.await(); // Wait till peers are ready
    action.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、主线程的逻辑

java 复制代码
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来协调多个任务线程的执行,并测量任务的总执行时间。希望这个详细的解释和示例能帮助你更好地理解代码的运行逻辑和输出效果!

相关推荐
摇滚侠44 分钟前
面试实战 问题二十四 Spring 框架中循环依赖问题的解决方法
java·后端·spring
三木水2 小时前
Spring-rabbit使用实战七
java·分布式·后端·spring·消息队列·java-rabbitmq·java-activemq
别来无恙1493 小时前
Spring Boot文件下载功能实现详解
java·spring boot·后端·数据导出
optimistic_chen3 小时前
【Java EE初阶 --- 网络原理】JVM
java·jvm·笔记·网络协议·java-ee
weixin_456904273 小时前
Java泛型与委托
java·spring boot·spring
悟能不能悟4 小时前
能刷java题的网站
java·开发语言
程序员陆通4 小时前
Java高并发场景下的缓存穿透问题定位与解决方案
java·开发语言·缓存
北执南念5 小时前
Java多线程基础总结
java
阿群今天学习了吗5 小时前
“鱼书”深度学习进阶笔记(3)第四章
人工智能·笔记·python·深度学习·算法
IT猿手5 小时前
2025年最新原创多目标算法:多目标酶作用优化算法(MOEAO)求解MaF1-MaF15及工程应用---盘式制动器设计,提供完整MATLAB代码
算法·数学建模·matlab·多目标优化算法·多目标算法