前言

如果要研究高并发,一般会借助高并发工具来进行测试。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. Chrome blocked third-party cookies

    Chrome blocked third-party cookies Chrome Incognito Chrome 无痕模式 https://support.google.com/chrome/an ...

  2. chrome device remote debug

    chrome device remote debug chrome://inspect/#devices chrome inspect devices Android chrome MIDI / MT ...

  3. how to get window width in javascript

    how to get window width in javascript how to get window width in js How to Detect Screen Resolution ...

  4. lua调用dll导出的函数

    参考手册 hello.dll #include "pch.h" #include "lua.hpp" #pragma comment(lib, "lu ...

  5. PHP实现一个二维码同时支持支付宝和微信支付

    实现思路 生成一个二维码,加入要处理的url连接 在用户扫完码后,在对应的脚本中,判断扫码终端,调用相应的支付 若能够扫码之后能唤起相应app,支付宝要用手机网站支付方式,微信要使用jsapi支付方式 ...

  6. APC推出鞋底缓震科技 两款中高端跑鞋将陆续上市

    近日,英国知名运动品牌APC(公司编号:08703733)推出了全新的鞋底缓震科技 NOVR,该项技术将首先应用于两款跑步鞋上,随后陆续应用到其他重点鞋类产品. 是对于各大运动品牌来说,鞋底研发一直是 ...

  7. pyhton的函数

    目录 一.函数引入 二.函数的定义 三.如何定义一个函数 四.定义函数的三种形式 1.空函数 2.有参函数 3.无参函数 五.函数的调用 六.函数的返回值 七.函数的参数 1.形参 1.1 位置形参 ...

  8. JPEG解码——(5)反量化和逆ZigZag变换

    本篇是该系列的第五篇,承接上篇huffman解码,介绍接下来的两个步骤--反量化和逆zigzag变换,即IDCT前的两个步骤. 需要说明的是,这两个步骤可以颠倒,本人的实现是,先反量化,再逆ZigZa ...

  9. ElasticSearch 数据建模

    公号:码农充电站pro 主页:https://codeshellme.github.io 通常在使用 ES 构建数据模型时,需要考虑以下几点: 字段类型 是否需要搜索与分词 是否需要聚合与排序 是否需 ...

  10. 追溯 MySQL Statement Cancellation Timer

    原文 1. 背景 在 jstack 的内容中可以看到以下的 MySQL Statement Cancellation Timer 守护线程, 在业务高峰期的时候会出现大量的这类守护线程, 由此追溯该线 ...