前言

如果要研究高并发,一般会借助高并发工具来进行测试。JCStress(Java Concurrency Stress)它是OpenJDK中的一个高并发测试工具,它可以帮助我们研究在高并发场景下JVM,类库以及硬件等状况。

JCStress学起来很简单,而且官方也提供了许多高并发场景下的测试用例,只要引入一个jar包,即可运行研究。

如何使用JCStress

此演示用maven工程,首先需要引入jar包,核心包是必须要的,样例包非必须要,此是为了演示其中的例子。

<dependencies>
<!-- jcstress 核心包 -->
<dependency>
<groupId>org.openjdk.jcstress</groupId>
<artifactId>jcstress-core</artifactId>
<version>0.3</version>
</dependency>
<!-- jcstress测试用例包 -->
<dependency>
<groupId>org.openjdk.jcstress</groupId>
<artifactId>jcstress-samples</artifactId>
<version>0.3</version>
</dependency>
</dependencies>

先写一个简单测试用例,一些注解不明白可以先不管,后面会讲解。此样例会在高并发下调用actor1和actor2方法各一次,按照正常逻辑,x最后的值要么是-1要么是5,如果actor2方法内的2行代码发生了指令重排序,就会导致x的值可能为0。

package com.nobody;

import org.openjdk.jcstress.annotations.*;
import org.openjdk.jcstress.infra.results.I_Result; /**
* @Description 测试指令重排序
* @Author Mr.nobody
* @Date 2021/4/6
* @Version 1.0
*/
@JCStressTest // 标记此类为一个并发测试类
@Outcome(id = {"0"}, expect = Expect.ACCEPTABLE_INTERESTING, desc = "wrong result") // 描述测试结果
@Outcome(id = {"-1", "5"}, expect = Expect.ACCEPTABLE, desc = "normal result") // 描述测试结果
@State //标记此类是有状态的
public class TestInstructionReorder { private boolean flag ;
private int x; public TestInstructionReorder() {} @Actor
public void actor1(I_Result r) {
if (flag) {
r.r1 = x;
} else {
r.r1 = -1;
}
} @Actor
public void actor2(I_Result r) {
this.x = 5;
flag = true;
}
}

配置程序的主类,org.openjdk.jcstress.Main是JCStress自带的一个启动类;然后可以配置-t参数设置需要测试的类,当然 -t 后面也可以指定包名,表示执行指定包下的所有测试类。如果不指定-t参数,默认会扫描项目下所有包的类。

运行程序,结果显示,x的值出现了0,-1,5三种结果,其中值为0不是我期待的,但是它在高并发下确实出现了,虽然相比其他值(几十万次)出现的概率(200多次)很低。

有些人会说用jmeter工具不也可以测试高并发,但是它们的侧重点还是不一样的,jmeter侧重对于接口整体的响应速度等进行测试,而JCStress框架能对某块逻辑代码进行高并发测试,更加侧重JVM,类库等领域的研究。

而且,JCStress会考虑不同JVM参数设置下的测试,而且自动帮我们设置,例如上图所示[-XX:-TieredCompilation]。

除了命令行窗口显示的测试结果之外,还会在项目所在的目录下生成 results文件夹,生成测试结果文档,其中index.html是测试总览,其他html文件是每个测试类的报告,结合结果数据结构可视化图形更加容易理解。

JCStress 注解说明

@JCStressTest

标记一个类为并发测试的类,它有一个org.openjdk.jcstress.annotations.Mode枚举类型的属性value。Mode.Continuous模式表示会运行几个Actor,Ariter线程,并收集统计结果。Mode.Termination模式代表运行具有阻塞/循环操作的单个Actor,看是否响应Singal信号。

@State

标记一个类是有状态的,即拥有可以读写的数据,例如上例的x和falg。State类只能是public的,不能是内部类(可以是静态内部类),并且得有一个默认构造方法。

@Outcome

描述测试的结果,它有3个属性,id属性为一个字符串数组,表示接收的结果,支持正则表达式;expect表示对观测结果的期望,它的值是一个枚举值;desc属性指定一个易于人类理解的对结果的描述。@Outcomes注解可以组合多个结果注解。

@Actor

@Actor是一个中心测试注解,它标记的方法会被一个特定的线程调用,每一个对象的方法只能被调用一次。多个Actro方法调用顺序是不保证的,它们是并发执行的,方法可以抛出异常并且会导致测试失败。Actor方法所在的类必须有State或者Result注解。

@Arbiter

它的作用其实和@Actor差不多,但是Arbiter标记的方法调用是在所有@Actor标记的方法调用之后,所以它标记的方法一般作为收集最后的结果来使用。

@Signal

此注解也是标记方法的,但是它是在JCStressTest的Termination模式下工作的,它的调用是在所有Actor之后。

@Result

它标记的类被作为测试结果的类,JCStress自带的org.openjdk.jcstress.infra.results包下就有大量的测试结果类,不同的类可以用来保持不同的结果。例如I_Result类有一个int类型的变量r1;II_Result类有2个int类型的变量r1和r2。

JCStress 插件

有一个插件集成了JCStress和Gradle,我们只需要在build.gradle中引入此插件,即可使用插件命令来进行测试。插件依赖为jcstress-gradle-plugin。

build.gradle文件如下,不同版本的插件集成了默认的JCStress版本,当然我们也可以自定义更改,如下最后一行所示。

apply plugin: 'java'
apply plugin: 'idea'
apply plugin: 'jcstress' buildscript {
repositories {
jcenter()
} dependencies {
classpath 'com.github.erizo.gradle:jcstress-gradle-plugin:0.8.1'
}
} ext {
jcstressVersion = '0.7'
} repositories {
jcenter()
} dependencies {
compile "org.openjdk.jcstress:jcstress-core:${jcstressVersion}"
} jcstress {
jcstressDependency "org.openjdk.jcstress:jcstress-core:${jcstressVersion}"
}

然后在项目即可编写测试类,例如还是上面那个例子,最后我们在项目根目录下执行 gradle jcstress,即可显示测试结果。也可以通过参数指定要测试的类,例如 gradle jcstress --tests "TestInstructionReorder"

插件源码地址:https://github.com/jerzykrlk/jcstress-gradle-plugin

Java高并发测试框架JCStress的更多相关文章

  1. java高并发测试代码

    package com.example.test; import java.net.URL;import java.net.URLConnection;import java.util.concurr ...

  2. Java高并发秒杀系统API之SSM框架集成swagger与AdminLTE

    初衷与整理描述 Java高并发秒杀系统API是来源于网上教程的一个Java项目,也是我接触Java的第一个项目.本来是一枚c#码农,公司计划部分业务转java,于是我利用业务时间自学Java才有了本文 ...

  3. 跟着阿里p7一起学java高并发 - 第19天:JUC中的Executor框架详解1,全面掌握java并发核心技术

    这是java高并发系列第19篇文章. 本文主要内容 介绍Executor框架相关内容 介绍Executor 介绍ExecutorService 介绍线程池ThreadPoolExecutor及案例 介 ...

  4. java高并发系列 - 第20天:JUC中的Executor框架详解2之ExecutorCompletionService

    这是java高并发系列第20篇文章. 本文内容 ExecutorCompletionService出现的背景 介绍CompletionService接口及常用的方法 介绍ExecutorComplet ...

  5. Java高并发如何解决

    Java高并发如何解决 对于我们开发的网站,如果网站的访问量非常大的话,那么我们就需要考虑相关的并发访问问题了.而并发问题是绝大部分的程序员头疼的问题,但话又说回来了,既然逃避不掉,那我们就坦然面对吧 ...

  6. Java高并发秒杀API之业务分析与DAO层

    根据慕课网上关于java高并发秒杀API的课程讲解用maven+ssm+redis实现的一个秒杀系统 参考了codingXiaxw's blog,很详细:http://codingxiaxw.cn/2 ...

  7. 转载:Java高并发,如何解决,什么方式解决

    原文:https://www.cnblogs.com/lr393993507/p/5909804.html 对于我们开发的网站,如果网站的访问量非常大的话,那么我们就需要考虑相关的并发访问问题了.而并 ...

  8. 【转】Java高并发,如何解决,什么方式解决

    原文地址:https://www.cnblogs.com/lr393993507/p/5909804.html 对于我们开发的网站,如果网站的访问量非常大的话,那么我们就需要考虑相关的并发访问问题了. ...

  9. java高并发系列 - 第24天:ThreadLocal、InheritableThreadLocal(通俗易懂)

    java高并发系列第24篇文章. 环境:jdk1.8. 本文内容 需要解决的问题 介绍ThreadLocal 介绍InheritableThreadLocal 需要解决的问题 我们还是以解决问题的方式 ...

随机推荐

  1. 加州金融专访NGK,就NGK DeFi+展开讨论

    近日,加利福尼亚金融日报联合数家知名媒体就DeFi+行业专访了NGK团队代表特德惠斯基. 首先,加利福尼亚金融日报专栏记者迈尔斯表示,目前区块链领域,去中心化金融(DeFi+)的概念是目前市场上面最火 ...

  2. django学习-20.python3中的特殊方法【__str__】的作用

    目录结构 1.前言 2.[__str__]特殊方法的具体使用 2.1.当使用print打印一个类被实例化后生成的对象的时候,若类里有定义了[__str__]特殊方法,是打印出这样的数据:[__str_ ...

  3. python的with用法(转载)

    原文地址:https://www.cnblogs.com/wanglei-xiaoshitou1/p/9238275.html 一.with语句是什么? 有一些任务,可能事先需要设置,事后做清理工作. ...

  4. 2021-2-22:请你说下 CAP 理论并举例

    CAP CAP 理论是分布式系统中的一个老生常谈的理论了,最早由 Eric Brewer 在一个讲座中提出.在这个讲座中,在传统 ACID 理论以及当时比较流行但是比较抽象的的设计指导理论 BASE ...

  5. 3分钟学会如何上手supervisor看门狗

    软硬件环境 centos7.6.1810 64bit cat /etc/redhat-release #查看系统版本 supervisor 3.4.0 python 2.7.5 supervisor简 ...

  6. JAVA 判断一个字符串是否是合法的日期格式?

    采用SimpleDateFormat类的parse方法进行判断,如果转换不成功,就会出现异常.另外,还需要判断字符串的长度,若不判断,第二个字符串就会验证通过,实际上也不是合法的.话不多说,且看代码: ...

  7. 用 hexo 快速搭建博客

    如何做到一毛不拔的搭建网站 以下操作全程使用管理员权限,因为我不清楚哪里会出现 permission denied 1.下载 nodejs 对应 windows 用户,下载对应的 ".msi ...

  8. Git:使用远程仓库

    远程仓库可使用Github.Gitee,或自建Gitlab.Gogs服务器,这里使用Github. 配置本地用户名和邮箱 # 配置本地用户的用户名邮箱(保存在用户.gitconfig文件) $ git ...

  9. C#正则实现匹配一块代码段

    最近项目,生成聚合网关,但是生成的网关文件中,存在着不必要的代码段,比如一个类A,类B等 之前一直使用手动删除,这么做劳民伤财,浪费时间,考虑使用正则写一个工具实现自动删除. 正则写法: string ...

  10. 摄像机+LookAt矩阵+视角移动+欧拉角

    一: 摄像机 OpenGL本身没有摄像机(Camera)的概念,但我们可以通过把场景中的所有物体往相反方向移动的方式来模拟出摄像机,产生一种我们在移动的感觉,而不是场景在移动. 以摄像机的视角作为场景 ...