并发测试工具Jcstress使用教程

Jcstress 全称 Java Concurrency Stress,是一种并发压力测试工具,可以帮助研究JVM、java类库和硬件中并发的正确性。

Wiki地址:https://wiki.openjdk.java.net/display/CodeTools/jcstress

Wiki中有一个Jcstress的example,可以根据example很方便入门使用jcstress。当然,我们也可以手动创建自己的Jcstress测试工程。

Maven例子

添加maven依赖

<dependency>
<groupId>org.openjdk.jcstress</groupId>
<artifactId>jcstress-core</artifactId>
<version>0.5</version>
</dependency>
<dependency>
<groupId>org.openjdk.jcstress</groupId>
<artifactId>jcstress-samples</artifactId>
<version>0.5</version>
</dependency>

pom.xml 可以如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>jfound</groupId>
<artifactId>jcstress-test</artifactId>
<version>1.0.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.openjdk.jcstress</groupId>
<artifactId>jcstress-core</artifactId>
<version>0.5</version>
</dependency>
<dependency>
<groupId>org.openjdk.jcstress</groupId>
<artifactId>jcstress-samples</artifactId>
<version>0.5</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>11</source>
<target>11</target>
</configuration>
</plugin>
</plugins>
</build>
</project>

新增一个测试类,这次以测试变量加 volatile 和不加 volatile 的区别。代码如下:

package jfound;
import org.openjdk.jcstress.annotations.*; public class VolatileTest {
@JCStressTest(Mode.Termination)
@Outcome(id = "TERMINATED", expect = Expect.ACCEPTABLE)
@Outcome(id = "STALE", expect = Expect.ACCEPTABLE_INTERESTING)
@State
public static class NoVolatile {
private int i = 0; @Actor
public void actor() {
while (i == 0) {
//nothing
}
}
@Signal
public void single() {
i = 1;
}
}
@JCStressTest(Mode.Termination)
@Outcome(id = "TERMINATED", expect = Expect.ACCEPTABLE)
@Outcome(id = "STALE", expect = Expect.FORBIDDEN)
@State
public static class AddVolatile {
private volatile int i = 0;
@Actor
public void actor() {
while (i == 0) {
//nothing
}
}
@Signal
public void single() {
i = 1;
}
}
}

VolatileTest 类里面有两个静态内部类,其中 NoVolatilei 是没有加 volatile 关键字的,AddVolatile 类中的 i 是有加 volatile 关键字的。

测试注解说明

  • org.openjdk.jcstress.annotations.JCStressTest

该注解标记一个类为一个并发测试的类,有一个属性 value 为 org.openjdk.jcstress.annotations.ModemodeContinuousTermination 两种模式。Continuous 模式是运行几个 org.openjdk.jcstress.annotations.Actororg.openjdk.jcstress.annotations.Ariter 线程,并收集结果。Termination 模式运行具有阻塞/循环操作的单个 ActorSingal 的测试。

  • org.openjdk.jcstress.annotations.Outcome

Outcome 是描述测试结果,并处理这个结果,该注解有 idexpectdesc 这三个属性。

其中 id 接收结果,如上面的 TERMINATEDSTALE 就是结果,id 还支持正则表达式;expect 是期望处理结果,类型为 org.openjdk.jcstress.annotationsExpect ,有 ACCEPTABLEACCEPTABLE_INTERESTINGFORBIDDENUNKNOWN 四种类型,ACCEPTABLE 表示接受当前结果,ACCEPTABLE 结果不一定会存在;ACCEPTABLE_INTERESTING 和 ACCEPTABLE 差不多,唯一不一样的是,这个结果会在生成的报告中高亮;FORBIDDEN 表示永远不应该出现的结果,若测试过程中有该结果,意味着测试失败; UNKNOWN 没有评分,不使用。

如上面例子所示,一个测试类 (JCStressTest) 中可以有一个或多个 Outcome

  • org.openjdk.jcstress.annotations.State

标记这个类是有状态的,有状态的意识是拥有数据,而且数据是可以被修改的,如上面测试例子中的 i , 其中 i 就是拥有的数据。为了方便理解,可以拿 Stateless 来做对比;如一些实体类是有状态(State)的,Service理应设置为无状态的 Sateless ,尽管service有属性,但是属性也是不能被修改的。

State 修饰的类必须是 public 的,不能是内部类,但是可以是静态内部类,如上面例子。

State 修饰的类必须有一个默认构造函数

  • org.openjdk.jcstress.annotations.Actor

该注解标记的方法会被线程调用,被 Actor 修饰方法所在的类必须有 State 或者 Result 注解,被其修饰的方法可以抛出异常,但是抛出异常的话,会引起测试失败。注意的是,Actor 标记的每个方法仅由一个特定线程调用,而且每个被 State 标记的实例仅调用每一个方法Actor 修饰的方法之间是没有顺序的,调用是并发执行的。

与之相对的还有 org.openjdk.jcstress.annotations.Arbiter 注解,Arbiter 注解和 Actor 注解差不多,不一样的是 Arbiter 注解声明的方法访问是在所有 State 之后,而且 Actor 所有的内存都对 Arbiter 可见,这就使得 Arbiter 在确认最终状态信息上有很大的作用。

  • org.openjdk.jcstress.annotations.Singal

改注解在 Termination 模式下是比较有用的,它标记的方法执行是在 Actor 标记方法执行之后。

  • org.openjdk.jcstress.annotations.Result

用改注解标记的类是测试结果的类,如 org.openjdk.jcstress.infra.results 下的类,该注解标记的类所有 field 都必须是原生数据类似或者是 String 类型,所有 field 都应该是 public。可以参考 org.openjdk.jcstress.infra.results 下的类。用法如下

@Actor
public void actor1(I_Result r) {
r.r1 = 1;
}

把测试结果用 Result 修饰的类接收,通常是配合 toString 打印出来。

  • org.openjdk.jcstress.annotations.Description

与测试无关,可以定义一些描述,方便查看

  • org.openjdk.jcstress.annotations.Ref

与测试无关,提供一些引用,如地址,ISBN等等。

  • org.openjdk.jcstress.annotations.JCStressMeta

DescriptionOutcomeRef 这些注解是可以放到一个公共类,然后由 JCStressMeta 注解引进来,以达到重复使用的目的。

运行及结果说明

在idea下执行如下

其中 Main class 填写 org.org.openjdk.jcstress.Main , 参数中的 -t 是指指定测试包名,不指定的话是默认扫描项目所有包。

在执行完成后,会在项目所在的目录下生成 results 文件夹,里面有个 index.html ,用浏览器打开即可查看报告。

总结

本文以一个例子展开来编写 Jcstress 并发测试工具的使用说明,并描述了 Jcstress 的所有核心注解,方便初学者去了解并借助该工具来学习并发编程。

JUC整理笔记三之测试工具jcstress的更多相关文章

  1. Erlang:[笔记三,构建工具rebar之使用依赖]

    概述 类似Java中的Maven,Gradle,在Erlang中同样也有包管理的工具,Rebar提供Erlang依赖(包)管理机制,开发人员可以重复使用已有的模块,通过rebar引入自己的项目直接使用 ...

  2. JUC整理笔记一之细说Unsafe

    JUC(java.util.concurrent)的开始,可以说是从Unsafe类开始. Unsafe 简介 Unsafe在sun.misc 下,顾名思义,这是一个不安全的类,因为Unsafe类所操作 ...

  3. JUC整理笔记二之聊聊volatile

    要想学好JUC,还得先了解 volatile 这个关键字.了解 volatile ,我们从一个例子开始吧. 本文不会很详细去说java内存模型,只是很简单地学习一下volatile 一个例子 pack ...

  4. C# 《编写高质量代码改善建议》整理&笔记 --(三)泛型&委托&事件

    1.泛型 基于泛型,我们可以将类型参数化,以便更大范围地进行代码复用.同时,它减少了泛型类及泛型方法中的转型, 确保类型安全. 1)总是优先考虑泛型 优点:可重用性,类型安全,高效率. 2)避免在泛型 ...

  5. Linux入门视频笔记三(常用工具集)

    一.全局变量(Linux中的全局变量指在整个系统中都能用的变量) 1.USER:当前登录系统的用户的用户名 2.HOME:当前用户的主目录 cd $HOME 或 cd ~可以进入用户主目录 3.PAT ...

  6. Android高手速成--第四部分 开发工具及测试工具

    第四部分 开发工具及测试工具 主要介绍和Android开发工具和测试工具相关的开源项目. 一.开发效率工具 Json2Java根据JSon数据自动生成对应的Java实体类,还支持Parcel.Gson ...

  7. jQuery整理笔记文件夹

    jQuery整理笔记文件夹 jQuery整理笔记一----jQuery開始 jQuery整理笔记二----jQuery选择器整理 jQuery整理笔记三----jQuery过滤函数 jQuery整理笔 ...

  8. 004-restful应用构建、分布式会话、测试工具简介

    一.概述 什么是rest(表述性状态转移,Representational State Transfer)是一种架构风格.他定义了创建可扩展Web服务的最佳实践. 1.Richardson成熟度模型 ...

  9. Web Capacity Analysis Tool 压力测试工具使用笔记

    一.背景介绍 Web Capacity Analysis Tool是微软轻量级Web压力测试工具, 早先是IIS 6.0Resource Tool kit 工具包中的一个组件,现在独立出来有一个社区版 ...

随机推荐

  1. 可运行的Java RMI示例和踩坑总结

    简述 资料参考: https://docs.oracle.com/javase/tutorial/rmi/overview.html https://blog.csdn.net/bigtree_372 ...

  2. How to get binary string from ArrayBuffer?

    https://stackoverflow.com/questions/16363419/how-to-get-binary-string-from-arraybuffer https://stack ...

  3. System Call

    内容 设计系统调用,将系统的相关信息(CPU型号.操作系统的版本号.系统中的进程等类似于Windows的任务管理器的信息)以文本形式列表显示于屏幕,并编写用户程序予以验证. 思想 系统调用是应用程序和 ...

  4. andorid jar/库源码解析之zxing

    目录:andorid jar/库源码解析 Zxing: 作用: 生成和识别,二维码,条形码. 栗子: 生成二维码,赋值到ImageView上 QRCodeWriter qrCodeWriter = n ...

  5. Pandas切片操作:很容易忽视的SettingWithCopyWarning

    Pandas是一个强大的分析结构化数据的工具集,主要用于数据挖掘和数据分析,同时也提供数据清洗功能. 很多初学者在数据的选取,修改和切片时经常面临一些困惑.这是因为Pandas提供了太多方法可以做同样 ...

  6. N - Subpalindromes URAL - 1989 哈希+线段树

    N - Subpalindromes URAL - 1989 这个是一个哈希+线段树,这个题目也不算特别难,但是呢,还比较有意思. 这个题目给你两个操作,一个是回答l~r 区间是不是回文,一个是对一个 ...

  7. 第一个Vue-cli

    第一步下载node.js https://nodejs.org/zh-cn/ 安装成功后 在cmd 输入 node -v 看看能不能打印出来 在cmd 输入 nmp-v 看看能不能打印出来 全局安装 ...

  8. README.md编写

    一.标题写法: 第一种方法: 1.在文本下面加上 等于号 = ,那么上方的文本就变成了大标题.等于号的个数无限制,但一定要大于0个哦.. 2.在文本下面加上 下划线 - ,那么上方的文本就变成了中标题 ...

  9. 【Hadoop离线基础总结】Hadoop的架构模型

    Hadoop的架构模型 1.x的版本架构模型介绍 架构图 HDFS分布式文件存储系统(典型的主从架构) NameNode:集群当中的主节点,主要用于维护集群当中的元数据信息,以及接受用户的请求,处理用 ...

  10. EOS基础全家桶(十一)智能合约IDE-EOS_Studio

    简介 我们马上要进入智能合约的开发了,以太坊最初提供了智能合约的功能,并宣告区块链进入2.0时代,而EOS的智能合约更进一步,提供了更多的便利性和可能性.为了进一步了解智能合约,并进行开发,我们需要先 ...