多线程压测方法模板

主要步骤

  • 创建一个线程池

    ExecutorService service = Executors.newFixedThreadPool(20);
    
  • 创建任务

    Runnable task = () -> {// 具体实现
    };
    
  • 提交多个任务到线程池

    for (int i = 0; i < 100000; i++) {service.submit(task);
    }
    
  • 关闭线程池

    service.shutdown();
    
  • 等待所有任务完成

    service.awaitTermination(1, TimeUnit.MINUTES);
    

示例一

以下是一个示例,使用多线程验证 IdGeneratorgenerateId 方法的准确性,测试其并发场景下是否会生成重复的 id。

import java.util.concurrent.*;
import java.util.*;public class Test {public static void main(String[] args) throws InterruptedException {// 创建一个线程池ExecutorService service = Executors.newFixedThreadPool(10);// 创建一个用于存储生成的 ID 的集合Set<String> idSet = Collections.synchronizedSet(new HashSet<>());// 创建一个名为 IdGenerator 的类,其中包含一个 generateId 方法class IdGenerator {String generateId() {// 在这里实现你的 ID 生成逻辑return UUID.randomUUID().toString();}}IdGenerator generator = new IdGenerator();// 创建一个任务,该任务调用 ID 生成方法并将结果添加到集合中Runnable task = () -> {String id = generator.generateId();if (idSet.contains(id)) {System.out.println("重复的 ID: " + id);} else {idSet.add(id);}};// 提交多个任务到线程池for (int i = 0; i < 10000; i++) {service.submit(task);}// 关闭线程池service.shutdown();// 等待所有任务完成service.awaitTermination(1, TimeUnit.MINUTES);System.out.println("生成的 ID 数量: " + idSet.size());}
}

这个程序会创建一个固定大小的线程池,并提交多个任务到线程池。每个任务都会调用 generateId 方法并将生成的 ID 添加到一个集合中。如果生成的 ID 已经存在于集合中,那么程序会打印出重复的 ID。最后,程序会打印出生成的 ID 的数量。

请注意,这只是一个基本的示例,你可能需要根据你的具体需求进行修改。例如,你可能需要调整线程池的大小任务的数量,或者 generateId 方法的实现。此外,如果你的 generateId 方法不是线程安全的,你可能需要添加适当的同步机制。如果你的 generateId 方法可能抛出异常,你可能需要添加适当的错误处理代码。最后,你可能需要添加更多的逻辑来更详细地检查生成的 ID(例如,检查 ID 的格式或长度)

示例二

首先,假设你的 ID 生成方法如下:

public class IdGenerator {public synchronized String generateUniqueId() {// 这里是生成唯一 ID 的逻辑,这里只是一个示例return UUID.randomUUID().toString();}
}

然后,编写测试类和测试方法:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.HashSet;
import java.util.Set;public class IdGeneratorTest {private static final IdGenerator idGenerator = new IdGenerator();private static final int THREAD_COUNT = 100; // 线程数量private static final int ID_COUNT = 1000; // 每个线程生成的 ID 数量public static void main(String[] args) throws InterruptedException {ExecutorService executorService = Executors.newFixedThreadPool(THREAD_COUNT);Set<String> allIds = new HashSet<>(); // 用于存储所有生成的 ID,以检查重复// 提交任务到线程池for (int i = 0; i < THREAD_COUNT; i++) {Runnable worker = new IdGeneratorTask(allIds, ID_COUNT);executorService.submit(worker);}// 所有任务完成之前,主线程等待executorService.shutdown();if (!executorService.awaitTermination(60, TimeUnit.SECONDS)) {System.out.println("一些任务未完成执行。");} else {System.out.println("所有 ID 已生成并检查完毕。");}// 检查是否有重复的 IDif (allIds.size() == THREAD_COUNT * ID_COUNT) {System.out.println("测试通过:没有发现重复的 ID。");} else {System.out.println("测试失败:发现了重复的 ID。");}}static class IdGeneratorTask implements Runnable {private final Set<String> allIds;private final int idCount;public IdGeneratorTask(Set<String> allIds, int idCount) {this.allIds = allIds;this.idCount = idCount;}@Overridepublic void run() {for (int i = 0; i < idCount; i++) {String id = idGenerator.generateUniqueId();synchronized (allIds) {if (!allIds.add(id)) {System.out.println("发现重复的 ID: " + id);}}}}}
}

这个程序创建了一个 IdGenerator 类,其中包含一个同步方法 generateUniqueId 用于生成 ID。IdGeneratorTest 类中的 main 方法设置了一个线程池,并提交了多个任务到线程池中。每个任务都是生成指定数量的 ID 并将它们添加到一个共享的 HashSet 中。使用 HashSet 是因为它不允许重复元素,如果尝试添加重复的 ID,add 方法将返回 false 并打印出重复的 ID。

请注意,这个示例使用了 UUID 作为 ID 生成方法,它几乎可以保证全局唯一性。如果你使用的是其他类型的 ID 生成算法,你需要确保它在多线程环境下的线程安全性。

我们还可以对程序进行一些改进,程序中使用 synchronized 关键字来同步对 allIds 集合的访问,这可能会导致性能瓶颈。我们可以使用 ConcurrentHashMap 来替代 HashSet,因为 ConcurrentHashMap 也能保证线程安全,并且性能更好。

下面是改进后的程序:

import java.util.concurrent.*;
import java.util.Map;
import java.util.UUID;public class IdGenerator {public String generateUniqueId() {// 假设这里是你的 ID 生成逻辑return UUID.randomUUID().toString();}
}public class IdGeneratorTest {private static final IdGenerator idGenerator = new IdGenerator();private static final int THREAD_COUNT = 100; // 线程数量private static final int ID_COUNT = 1000; // 每个线程生成的 ID 数量private static final Map<String, Integer> idCounts = new ConcurrentHashMap<>();public static void main(String[] args) throws InterruptedException {ExecutorService executorService = Executors.newFixedThreadPool(THREAD_COUNT);// 提交任务到线程池for (int i = 0; i < THREAD_COUNT; i++) {executorService.submit(new IdGeneratorTask());}executorService.shutdown();if (!executorService.awaitTermination(60, TimeUnit.SECONDS)) {System.out.println("一些任务未完成执行。");} else {System.out.println("所有 ID 已生成并检查完毕。");checkForDuplicates();}}static class IdGeneratorTask implements Runnable {@Overridepublic void run() {for (int i = 0; i < ID_COUNT; i++) {String id = idGenerator.generateUniqueId();int count = idCounts.getOrDefault(id, 0) + 1;idCounts.put(id, count);}}}private static void checkForDuplicates() {idCounts.forEach((id, count) -> {if (count > 1) {System.out.printf("发现重复的 ID: %s (重复次数: %d)%n", id, count);}});}
}

在这个改进的程序中,我们使用了 ConcurrentHashMap 来记录每个 ID 的出现次数。如果某个 ID 的出现次数大于 1,说明它是重复的,程序将打印出具体的重复 ID 及其重复次数。

请注意,这个示例使用了 UUID 作为 ID 生成方法,它几乎可以保证全局唯一性。如果你的 ID 生成算法不是基于 UUID,那么你需要确保它在多线程环境下的线程安全性。此外,awaitTermination 方法的超时时间根据实际情况进行调整。

真实案例

错误的 generateId 方法实现:

synchronized String generateId() {// 在这里实现你的 ID 生成逻辑// 有问题的实现(并发场景下)Random random = new Random();Integer number = random.nextInt(9000) + 1000;SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");return sdf.format(new Date()) + String.valueOf(number);
}

改进的 generateId 方法实现:

synchronized String generateId() {// 在这里实现你的 ID 生成逻辑// 改进的实现:String dateStr = LocalDate.now().format(DateTimeFormatter.ofPattern("yyMMdd"));Duration duration = Duration.between(LocalTime.of(0, 0, 0), LocalTime.now());String secondsOfTimeStr = StringUtils.leftPad(String.valueOf(duration.getSeconds()), 5, "0");String key = dateStr + secondsOfTimeStr;String value = redisTemplate.opsForValue().get(key);if (null == value) {value = redisTemplate.opsForValue().increment(key).toString();redisTemplate.expire(key, 60L, TimeUnit.SECONDS);} else {value = redisTemplate.opsForValue().increment(key).toString();}String x = key + StringUtils.leftPad(value, 4, "0");return x;
}

至此,over~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/41473.shtml

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

相关文章

【大数据面试题】35 Spark 怎么做优化?

一步一个脚印,一天一道大数据面试题 博主希望能够得到大家的点赞收,藏支持!非常感谢~ 点赞,收藏是情分,不点是本分。祝你身体健康,事事顺心! Spark 如何做优化一直是面试过程中常问的问题。那么这次也仅以此篇文章总结梳理,希望对大家有帮助。 通用优化 Spark 一般遇…

Infinitar链游新发展新机遇

区块链游戏市场在近年来经历了显著增长&#xff0c;吸引了大量的投资和关注。随着加密货币和NFT&#xff08;非同质化代币&#xff09;概念的普及&#xff0c;越来越多的投资者、游戏开发者和看到了区块链技术在游戏领域的应用潜力&#xff0c;纷纷涌入市场。区块链游戏的用户量…

compressor.js一款基于浏览器的JavaScript 图片压缩javascript库

今天&#xff0c;我们就来聊聊一个轻量级的 JavaScript 图像压缩库 —— Compressor.js&#xff0c;它和 Node 端的 Sharp.js 一样&#xff0c;都是图片处理的利器&#xff0c;但Compressor.js 更擅长在浏览器端进行操作。 什么是 Compressor.js Compressor.js&#xff0c;就是…

Aigtek功率放大器的参数及应用是什么

功率放大器是电子电路中的重要组成部分&#xff0c;用于将输入信号的功率增加到更高的水平。它们在各种电子设备和应用中发挥着关键作用。下面Aigtek安泰电子将介绍功率放大器的主要参数以及它们在不同领域的应用。 1.功率放大器的基本参数 增益 功率放大器的增益是指输出信号的…

android应用的持续构建CI(五)-- 应用管理

一、ER设计 渠道&#xff1a;应用发布的渠道&#xff0c;To B的话&#xff0c;可能是学校、租户等&#xff1b;To C的话&#xff0c;渠道则是不同厂商的应用市场。审核&#xff1a;jenkins构建应用完成后&#xff0c;管理后台生成应用的审核记录。 下面是每个实体详细的字段&a…

CAN总线协议

CAN总线协议&#xff0c;全程为控制器局域网&#xff08;Controller Area Network&#xff09;协议&#xff0c;是一种用于实时应用的串行通讯协议。该协议由德国某公司专门为汽车行业开发&#xff0c;并逐渐成为一种标准&#xff0c;这是国际上应用最广泛的现场总线之一。 一…

昇思25天学习打卡营第17天(+1)|Diffusion扩散模型

1. 学习内容复盘 本文基于Hugging Face&#xff1a;The Annotated Diffusion Model一文翻译迁移而来&#xff0c;同时参考了由浅入深了解Diffusion Model一文。 本教程在Jupyter Notebook上成功运行。如您下载本文档为Python文件&#xff0c;执行Python文件时&#xff0c;请确…

Git仓库介绍

1. Github GitHub 本身是一个基于云端的代码托管平台&#xff0c;它提供的是远程服务&#xff0c;而不是一个可以安装在本地局域网的应用程序。因此&#xff0c;GitHub 不可以直接在本地局域网进行安装。 简介&#xff1a;GitHub是最流行的代码托管平台&#xff0c;提供了大量…

昇思MindSpore学习笔记4-02生成式--DCGAN生成漫画头像

摘要&#xff1a; 记录了昇思MindSpore AI框架使用70171张动漫头像图片训练一个DCGAN神经网络生成式对抗网络&#xff0c;并用来生成漫画头像的过程、步骤。包括环境准备、下载数据集、加载数据和预处理、构造网络、模型训练等。 一、概念 深度卷积对抗生成网络DCGAN Deep C…

STM32+ESP8266(ESP32)+MQTT+阿里云物联网平台

1、阿里云物联网平台 - 阿里云物联网平台配置 产品-设备-编辑物模型-设备端开发-查看上报数据 在产品上添加物模型&#xff0c;然后设备是继承自产品的&#xff0c;因此也具有物模型 添加产品、添加设备、产品上添加物模型 - 使用IOT Studio 绘制界面显示温度、湿度、灯开…

Tomcat(+Servlet)笔记+代码

Tomcat安装和配置 安装在不含中文的路径&#xff0c;路径不能太长 Apache 官网&#x1f447; Apache Tomcat - Welcome! 配置部分 点击下图红框处&#xff0c;找到Tomcat安装位置 添加项目的文件 配好的话&#xff0c;红框这里有个猫 代码部分 新建jsp文件&#xff0c;里…

1019记录

人瑞 - SDK - 外派米哈游 1&#xff0c;接口测试的工具 回答的是postman&#xff0c; 改进&#xff1a;JMeter 2&#xff0c;接口502&#xff0c;什么问题导致的&#xff1f;如何定位&#xff1f; 参考答案&#xff1a;502错误定义&#xff1a;是网关错误&#xff0c; 通俗…

【MotionCap】在wsl2 ubuntu20.04构建及运行

https://github.com/MVIG-SJTU/AlphaPose/issues/1157conda create -n alphapose python=3.7 -y conda activate alphapose conda install pytorch==1.12.1 torchvision==0.13.1 torchaudio==0.12.1

如何用CSS3画一条0.5px的直线?

在 CSS 中,实际上无法直接指定 0.5px 的线条粗细,因为 CSS 中的像素单位是最小单位,通常无法表示小数像素。但是,可以通过一些技巧来模拟出看起来像是 0.5px 粗细的线条,例如使用伪元素和缩放等技巧。 以下是一种近似实现 0.5px 线条的方法: .line {position: relative…

线程(基础概念)

文章目录 一、线程和进程&#xff1f;二、线程初识2.1 线程属性2.2 线程的调度策略2.3 线程的优先级2.3 线程实验 一、线程和进程&#xff1f; 我们经常描述进程&#xff08;process&#xff09;和线程&#xff08;thread&#xff09;&#xff1a; 进程是资源管理的最小单位&a…

昇思25天学习打卡营第07天 | 函数式自动微分

昇思25天学习打卡营第07天 | 函数式自动微分 文章目录 昇思25天学习打卡营第07天 | 函数式自动微分函数与计算图微分函数与梯度Stop GradientAuxiliary data 神经网络梯度计算总结打卡 神经网络的训练主要使用反向传播算法&#xff0c;首先计算模型预测值&#xff08;logits&am…

科普文:微服务之服务网格Service Mesh

一、ServiceMesh概念 背景 随着业务的发展&#xff0c;传统单体应用的问题越来越严重&#xff1a; 单体应用代码库庞大&#xff0c;不易于理解和修改持续部署困难&#xff0c;由于单体应用各组件间依赖性强&#xff0c;只要其中任何一个组件发生更改&#xff0c;将重新部署整…

Android SurfaceFlinger——创建Layer(二十)

上一篇文章介绍到,SurfaceComposerClient 中的 createSurface() 方法最终创建的是一个 Layer,这里我们接着看 Layer 的创建。 一、Layer创建 1、SurfaceFlinger.cpp 源码位置:/frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp status_t SurfaceFlinger:…

MUNIK解读ISO26262--什么是DFA

我们在学习功能安全过程中&#xff0c;经常会听到很多安全分析方法&#xff0c;有我们熟知的FMEA(Failure Modes Effects Analysis)和FTA(Fault Tree Analysis)还有功能安全产品设计中几乎绕不开的FMEDA(Failure Modes Effects and Diagnostic Analysis)&#xff0c;相比于它们…

VBA中打开、保存关闭Excel工作簿的方法

前言 本节会介绍使用VBA方法打开Excel工作簿、保存关闭Excel工作簿的方法&#xff0c;分别会用到Open、Save、Close方法的使用。 1.使用Open方法打开工作簿 Workbooks.Open(FileName,UpdateLinks,ReadOnly,Format,Password,WriteResPassword,Ignore-ReadOnlyResommended,Orig…