测试目的
本次测试目的是 消费 Redis List类型 里的数据 以各种方式来快速消费,得到最佳消费方式。消费框架为 spring boot,消费工具库为 lettuce,结合redisredisTemplate 的 api 来载入和消费数据,消费数据量分别为 1.5w、2w、10w。消费数据会提前加载到 Redis list 中,消费api 为 redisredisTemplate.opsForList().rightPop(key, Duration.ofSeconds(3)),该api 被封装为 redisSdk.LRightPopBlock(key,second)。
使用 ForkJoinPool 的方式测试
ForkJoinPool 的优势在于,可以充分利用多cpu,多核cpu的优势,把一个任务拆分成多个“小任务”,把多个“小任务”放到多个处理器核心上并行执行;当多个“小任务”执行完成之后,再将这些执行结果合并起来即可。线程的数量是通过构造函数传入,如果没有向构造函数中传入希望的线程数量,那么当前计算机可用的CPU数量会被设置为线程数量作为默认值。
测试机配置
CPU 类型
基准速度
系统类型
内存
内核
逻辑CPU
Intel(R) Core(TM) i7-8565U CPU @ 1.80GHz
1.99 GHz
64位
8G
4
8
单线程测试
单线程不存在 ForkJoinPool 的方式,所以这里没用到。
@Override
public void run(String... args) throws Exception {
long sumTime = 0;
while(true){
try{
long startTime = System.currentTimeMillis();
String str = redisSdk.LRightPopBlock("a",3);
if(!StrUtil.isEmpty(str)) {
long endTime = System.currentTimeMillis();
sumTime += endTime - startTime;
log.info("处理数据 {}, 累计时间 {}",str,sumTime);
}
}catch(Exception e){
log.error(e.getMessage());
}
}
}
测试结果
处理 15000 条数据,所需耗时 444s
ForkJoinPool 多线程消费代码
public void test2(){
int fcore = 2;
ForkJoinPool forkJoinPool = new ForkJoinPool(fcore);
AtomicInteger count = new AtomicInteger(0);
AtomicInteger breaks = new AtomicInteger(0);
long startTime = System.currentTimeMillis();
IntStream.range(0,fcore).forEach(j ->{
forkJoinPool.execute(() -> {
while (true) {
try {
String str = redisSdk.LRightPopBlock("a", 3);
if (!StrUtil.isEmpty(str)) {
log.info("累计处理 {} 条数据", count.incrementAndGet());
} else {
breaks.incrementAndGet();
break;
}
} catch (Exception e) {
log.error(e.getMessage());
}
}
});
});
while(true) {
try {
if(count.get() >= 15000) {
break;
}
Thread.sleep(500);
}catch(Exception e){
e.printStackTrace();
}
}
long endTime = System.currentTimeMillis();
log.info("总耗时 {}",endTime - startTime - 1000);
}
测试结果
并行