网站首页 > java教程 正文
在软件测试中,经常会遇到随机数。我简单分成了两类:
- 简单取随机数;
- 从一个集合中随机取值。
其实第二个场景包含在第一个场景内。对于接口测试来说,通常我们直接使用第二种场景比较多,就是从某一个集合中随机取一个值。如果更复杂一些,每个值拥有不同的权重,其中这个也可以转化成第二个场景来说。
缘起
为什么要把第二个场景和第一个场景分开呢,这个问题源于之前写过的文章ConcurrentHashMap性能测试,当时发现自己封装的com.funtester.frame.SourceCode#random(java.util.List<F>)方法性能存在瓶颈,特别消耗CPU资源。
虽然单机QPS也在50万+,但是因为这个方法很多地方都会用到,所以还是想提升一些性能。所以我就搜索了一些高性能随机数的功能,跟我之前搜到的资料一致,使用java.util.concurrent.ThreadLocalRandom这个实现类是性能最高的,方法如下:
/**
* 获取随机数,获取1~num 的数字,包含 num
*
* @param num 随机数上限
* @return 随机数
*/
public static int getRandomInt(int num) {
return ThreadLocalRandom.current().nextInt(num) + 1;
}
针对第二种场景,还有一种实现思路:通过循环去集合中取即可。就是顺序去取,而不是每次都从集合中随机。
举个例子,我们有10万测试用户进行流量回放,演示代码如下:
def funtest = {
random(drivers).getGetResponse(random(urls))
}
new FunQpsConcurrent(funtest).start()
这里调用了两次com.funtester.frame.SourceCode#random(java.util.List<F>),当QPS到达10万级别时候,理论上这个方法导致的瓶颈还是有一些影响的。
多线程
所以我用了新思路进行改造,下面是两种思路的对比压测用例,这个测试用例里面其实有三个实现:
- random
- AtomicInteger
- int
用例如下:
package com.funtest.groovytest
import com.funtester.base.constaint.FixedThread
import com.funtester.frame.SourceCode
import com.funtester.frame.execute.Concurrent
import java.util.concurrent.atomic.AtomicInteger
class FunTest extends SourceCode {
static int times = 1000
static int thread = 500
static def integers = 0..100 as List
static def integer = new AtomicInteger()
static def i = 0
static def size = integers.size()
public static void main(String[] args) {
RUNUP_TIME = 0
new Concurrent(new FunTester(), thread, "测试随机数性能").start()
}
private static class FunTester extends FixedThread {
FunTester() {
super(null, times, true)
}
@Override
protected void doing() throws Exception {
10000.times {random(integers)}
// 10000.times {integers.get(integer.getAndIncrement() % size)}
// 10000.times {integers.get(i++ % size)}
}
@Override
FunTester clone() {
return new FunTester()
}
}
}
由于测试中均达到了CPU硬件瓶颈,相同参数情况下结论比较明显,就没有进行多轮的对比测试。下面分享一下测试结果:
- random:1151
- AtomicInteger:3152
- int:2273
没想到用了java.util.concurrent.atomic.AtomicInteger反而性能更高了,这个问题略微有点深奥,暂时没有思路。
单线程
下面我们来测试一下单线程的性能,下面是我的用例:
package com.funtest.groovytest
import com.funtester.frame.SourceCode
import java.util.concurrent.atomic.AtomicInteger
class FunTestT extends SourceCode {
static int times = 1000000
static def integers = 0..100 as List
static def integer = new AtomicInteger()
static def i = 0
static def size = integers.size()
public static void main(String[] args) {
time {
// times.times {random(integers)}
// times.times {integers.get(integer.getAndIncrement() % size)}
times.times {integers.get(i++ % size)}
} , "随机数性能测试"
}
}
下面是测试结果,这里我记录了执行完所有循环次数的时间,单位是ms(毫秒)。
- random:763
- AtomicInteger:207
- int:270
这下结论明确了,就java.util.concurrent.atomic.AtomicInteger了。
末了
最终写了一个新的随机对象的方法:
/**
* 随机选择某个对象
*
* @param list
* @param index 自增索引
* @param <F>
* @return
*/
public static <F> F random(List<F> list, AtomicInteger index) {
if (list == null || list.isEmpty()) ParamException.fail("数组不能为空!");
return list.get(index.getAndIncrement() % list.size());
}
「BUG挖掘机·性能征服者·头顶锅盖」
- 上一篇: 在程序中用的随机数,足够随机吗?
- 下一篇: Java修炼终极指南:31. 创建伪随机数生成器的流
猜你喜欢
- 2024-09-08 JavaWeb项目各种随机数主键ID的代码范例供大家参考学习
- 2024-09-08 Java中List集合有哪些特性?Java开发常见集合
- 2024-09-08 这么一篇.Java性能权威指南.不需要好好的了解一下吗?
- 2024-09-08 一篇文章彻底弄懂CAS实现SSO单点登录原理
- 2024-09-08 Java练习:输出并统计水仙花数、猜数字小游戏
- 2024-09-08 Javaweb代码创建JESESSION32位随机数及session最大不活动时间
- 2024-09-08 Java 中生成一组不重复随机整数的简便方法
- 2024-09-08 JDK 17 - Java 17 的新特性速览(java的什么特性实现了软件开发人员一次编写)
- 2024-09-08 Java教学:Integer、日期类、数字类、随机数、枚举,一次搞定!
- 2024-09-08 Java程序员面试宝典:用这100个问答搞定面试官
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- java反编译工具 (77)
- java反射 (57)
- java接口 (61)
- java随机数 (63)
- java7下载 (59)
- java数据结构 (61)
- java 三目运算符 (65)
- java对象转map (63)
- Java继承 (69)
- java字符串替换 (60)
- 快速排序java (59)
- java并发编程 (58)
- java api文档 (60)
- centos安装java (57)
- java调用webservice接口 (61)
- java深拷贝 (61)
- 工厂模式java (59)
- java代理模式 (59)
- java.lang (57)
- java连接mysql数据库 (67)
- java重载 (68)
- java 循环语句 (66)
- java反序列化 (58)
- java时间函数 (60)
- java是值传递还是引用传递 (62)
本文暂时没有评论,来添加一个吧(●'◡'●)