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

多线程压测方法模板

主要步骤

  • 创建一个线程池

    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~

相关文章:

多线程压测方法模板

主要步骤 创建一个线程池 ExecutorService service Executors.newFixedThreadPool(20);创建任务 Runnable task () -> {// 具体实现 };提交多个任务到线程池 for (int i 0; i < 100000; i) {service.submit(task); }关闭线程池 service.shutdown();等待所有任务完成 s…...

Uniapp软件库全新带勋章功能(包含前后端源码)

源码介绍&#xff1a; Uniapp开发的软件库全新带勋章功能&#xff0c;搭建好后台 在前端找到 util 这个文件 把两个js文件上面的填上自己的域名&#xff0c;电脑需要下载&#xff1a;HBuilderX 登录账号 没有账号就注册账号&#xff0c; 然后上传文件&#xff0c;打包选择 “…...

秋招突击——7/5——设计模式知识点补充——适配器模式、代理模式和装饰器模式

文章目录 引言正文适配器模式学习篮球翻译适配器 面试题 代理模式学习面试题 装饰器模式学习装饰模式总结 面试题 总结 引言 为了一雪前耻&#xff0c;之前腾讯面试的极其差&#xff0c;设计模式一点都不会&#xff0c;这里找了一点设计模式的面试题&#xff0c;就针对几个常考…...

bmob Harmony鸿蒙快速开发搜索功能

搜索功能是很多应用都需要的功能。在很多平台上&#xff0c;要开发一个兼容性较好的搜索功能都还是需要添加比较多的视图代码的。 为了解决这个问题&#xff0c;鸿蒙ArkUI提供了一个快速添加搜索功能的视图组件给我们&#xff0c;结合Bmob Harmony鸿蒙SDK的搜索能力&#xff0…...

软通动力子公司鸿湖万联最新成果SwanLink AI亮相世界人工智能大会

7月4日&#xff0c;2024世界人工智能大会暨人工智能全球治理高级别会议&#xff08;WAIC 2024&#xff09;在上海拉开帷幕&#xff0c;软通动力董事长兼首席执行官刘天文受邀出席开幕式。其间&#xff0c;软通动力携子公司鸿湖万联深度参与到大会各项活动中&#xff0c;并全面展…...

查看Linux系统中日志文件

Linux 系统中 Ubuntu&#xff0c;Debian&#xff0c;CentOS&#xff0c;RedHat 作为常用的服务器软件系统&#xff0c;很多人都已经熟知。不论是服务器出现问题&#xff0c;还是日常维护或各种环境搭建&#xff0c;我们经常需要登录上服务器查看日志。 如果熟知 Linux 下的 ta…...

技术干货|如何轻松完成空调管路的随机振动分析以及疲劳寿命预测

基于NVHD 的虚拟路面谱激励车内结构路噪优化 作者&#xff1a;戴相花 颜磊 吕霞 杨凯 单位&#xff1a;苏州三星电子有限公司 论文摘要 随机振动试验是评估空调管路流通振动耐久性的重要试验之一。本文以某型号空调管路系统为研究对象&#xff0c;评估空调管路随机振动疲劳…...

中英双语介绍中国的城市:上海市(Shanghai)

中文版 上海市是中国最大的城市之一&#xff0c;也是全球重要的金融、贸易和航运中心。作为一座现代化的国际大都市&#xff0c;上海以其繁华的商业区、丰富的文化遗产和多样化的经济结构而闻名。以下是对上海市的详细介绍&#xff0c;包括其地理位置、人口、经济、教育、文化…...

代码随想录算法训练营第75天:总结篇[1]

代码随想录算法训练营第75天&#xff1a;总结篇 代码随想录姑且是都过了一遍了&#xff0c;最开始了解到的时候还不会c语法&#xff0c;跟着学习还是有难度的&#xff0c;也很难坚持着去写题&#xff0c;后面决定加入训练营与大家齐头并进&#xff0c;刚开始气氛很好&#xff…...

眼动追踪技术 | 眼动的分类和模型

摘要 灵长类动物用于调整中央凹位置的正常眼动&#xff0c;几乎都可以归结为五种基本类型的组合&#xff1a;扫视、平稳追踪、聚散、前庭眼震和生理性眼震(与注视相关的微小运动)。聚散运动用于将双眼聚焦于远处的目标(深度知觉)。其他运动(如适应和聚焦)指的是眼动的非位置变…...

如何使用PHP根据输入文字动态调整图片尺寸?

根据文字改变图片尺寸的PHP代码 以下是一个使用PHP实现根据输入的文字动态调整图片尺寸的示例代码。该代码使用GD库来处理图片。 1. 创建HTML表单 首先&#xff0c;我们需要一个HTML表单来接受用户输入的文字和新的图片尺寸。 <!DOCTYPE html> <html lang"en…...

3.js - hdr贴图 是什么,有什么用

HDR贴图&#xff1a;High-Dynamic Range&#xff08;高动态范围&#xff09;贴图 一、定义与特点 定义&#xff1a;HDR贴图是具有高动态范围的环境贴图&#xff0c;能够捕捉并保留丰富的亮部细节和暗部细节&#xff0c;从而模拟出更加真实的光照效果。特点&#xff1a; 高动态…...

Nature Communications|用于电子皮肤的自主自愈晶体管(柔性半导体器件/电子皮肤/柔性电子)

2024年4月23日,韩国庆熙大学Jin Young Oh,美国斯坦福大学鲍哲南(Zhenan Bao)和韩国嘉泉大学Tae Il Lee团队,在《Nature Communications》上发布了一篇题为“Autonomous self-healing supramolecular polymer transistors for skin electronics”的论文。论文内容如下: 一…...

6月30日功能测试Day10

3.4.4拼团购测试点 功能位置&#xff1a;营销-----拼团购 后台优惠促销列表管理可以添加拼团&#xff0c;查看拼团活动&#xff0c;启动活动&#xff0c;编辑活动&#xff0c;删除活动。 可以查看拼团活动中已下单的订单以状态 需求分析 功能和添加拼团 商品拼团活动页 3…...

无人机对地面运动目标定位---获取目标的移动方向和速度

目录 一、引子 我们利用单目无人机通过等时间间隔拍照的形式对地面某移动目标进行定位&#xff0c;当前&#xff0c;我们已经获得了每张相片上该目标的三维坐标&#xff0c;并且知道该无人机在飞行过程中拍照的时间间隔&#xff0c;那么我们就可以通过一定的计算&#xff0c;得…...

管理才是最根本的核心竞争力

相信大家对于华为提出的“管理是核心竞争力”“管理才是企业的核心竞争力”等言论并不陌生&#xff0c;而华为的确也一直践行这样的理念。比如&#xff0c;在华为发展历史上很艰难的2002年&#xff0c;华为仍然坚持重点抓管理。总裁任正非后来提到&#xff1a;“2002年华为快崩…...

Raid阵列中硬盘损坏后,新硬盘可以直接换上吗?

RAID更换的方式基本类似&#xff0c;这里以RAID 1为例。 1. 关闭服务器&#xff1a;确保服务器或RAID控制器处于关闭或已停止状态&#xff0c;以避免数据写入或损坏。确定损坏硬盘&#xff1a;通过RAID控制器的管理界面&#xff0c;确定哪一块硬盘在RAID 中损坏。 2. 拆卸原硬…...

Python爬虫康复训练——笔趣阁《神魂至尊》

还是话不多说&#xff0c;很久没写爬虫了&#xff0c;来个bs4康复训练爬虫&#xff0c;正好我最近在看《神魂至尊》&#xff0c;爬个txt文件下来看看 直接上代码 """ 神魂至尊网址-https://www.bqgui.cc/book/1519/ """ import requests from b…...

Kaptcha验证码

Kaptcha验证码 Kaptcha 是一个用于生成验证码的开源库&#xff0c;在 Java 中使用它可以轻松地为应用程序添加验证码功能。 一、引入依赖 首先&#xff0c;需要在项目的 pom.xml 文件&#xff08;如果是 Maven 项目&#xff09;中添加 Kaptcha 的依赖&#xff1a; <depend…...

Rufus 制作启动盘 | 便携的工作空间

唠唠闲话 最近服务器硬盘故障多&#xff0c;在修复过程中&#xff0c;学习了一些操作&#xff0c;这里做个记录。本期主要介绍 U盘启动盘的制作&#xff0c;以及持久化存储。 U 盘启动盘 镜像选择 Ubuntu 的版本命名遵循 “Adjective Animal” 的模式&#xff0c;即 “形容…...

wordpress后台更新后 前端没变化的解决方法

使用siteground主机的wordpress网站&#xff0c;会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后&#xff0c;网站没有变化的情况。 不熟悉siteground主机的新手&#xff0c;遇到这个问题&#xff0c;就很抓狂&#xff0c;明明是哪都没操作错误&#x…...

日语AI面试高效通关秘籍:专业解读与青柚面试智能助攻

在如今就业市场竞争日益激烈的背景下&#xff0c;越来越多的求职者将目光投向了日本及中日双语岗位。但是&#xff0c;一场日语面试往往让许多人感到步履维艰。你是否也曾因为面试官抛出的“刁钻问题”而心生畏惧&#xff1f;面对生疏的日语交流环境&#xff0c;即便提前恶补了…...

C++初阶-list的底层

目录 1.std::list实现的所有代码 2.list的简单介绍 2.1实现list的类 2.2_list_iterator的实现 2.2.1_list_iterator实现的原因和好处 2.2.2_list_iterator实现 2.3_list_node的实现 2.3.1. 避免递归的模板依赖 2.3.2. 内存布局一致性 2.3.3. 类型安全的替代方案 2.3.…...

AI Agent与Agentic AI:原理、应用、挑战与未来展望

文章目录 一、引言二、AI Agent与Agentic AI的兴起2.1 技术契机与生态成熟2.2 Agent的定义与特征2.3 Agent的发展历程 三、AI Agent的核心技术栈解密3.1 感知模块代码示例&#xff1a;使用Python和OpenCV进行图像识别 3.2 认知与决策模块代码示例&#xff1a;使用OpenAI GPT-3进…...

基于Flask实现的医疗保险欺诈识别监测模型

基于Flask实现的医疗保险欺诈识别监测模型 项目截图 项目简介 社会医疗保险是国家通过立法形式强制实施&#xff0c;由雇主和个人按一定比例缴纳保险费&#xff0c;建立社会医疗保险基金&#xff0c;支付雇员医疗费用的一种医疗保险制度&#xff0c; 它是促进社会文明和进步的…...

visual studio 2022更改主题为深色

visual studio 2022更改主题为深色 点击visual studio 上方的 工具-> 选项 在选项窗口中&#xff0c;选择 环境 -> 常规 &#xff0c;将其中的颜色主题改成深色 点击确定&#xff0c;更改完成...

蓝牙 BLE 扫描面试题大全(2):进阶面试题与实战演练

前文覆盖了 BLE 扫描的基础概念与经典问题蓝牙 BLE 扫描面试题大全(1)&#xff1a;从基础到实战的深度解析-CSDN博客&#xff0c;但实际面试中&#xff0c;企业更关注候选人对复杂场景的应对能力&#xff08;如多设备并发扫描、低功耗与高发现率的平衡&#xff09;和前沿技术的…...

Nuxt.js 中的路由配置详解

Nuxt.js 通过其内置的路由系统简化了应用的路由配置&#xff0c;使得开发者可以轻松地管理页面导航和 URL 结构。路由配置主要涉及页面组件的组织、动态路由的设置以及路由元信息的配置。 自动路由生成 Nuxt.js 会根据 pages 目录下的文件结构自动生成路由配置。每个文件都会对…...

音视频——I2S 协议详解

I2S 协议详解 I2S (Inter-IC Sound) 协议是一种串行总线协议&#xff0c;专门用于在数字音频设备之间传输数字音频数据。它由飞利浦&#xff08;Philips&#xff09;公司开发&#xff0c;以其简单、高效和广泛的兼容性而闻名。 1. 信号线 I2S 协议通常使用三根或四根信号线&a…...

Selenium常用函数介绍

目录 一&#xff0c;元素定位 1.1 cssSeector 1.2 xpath 二&#xff0c;操作测试对象 三&#xff0c;窗口 3.1 案例 3.2 窗口切换 3.3 窗口大小 3.4 屏幕截图 3.5 关闭窗口 四&#xff0c;弹窗 五&#xff0c;等待 六&#xff0c;导航 七&#xff0c;文件上传 …...