测试多线程代码是一个艰巨的挑战。 尝试测试并发性时获得的第一个建议是尽可能地在代码中隔离并发问题。 这是一般的设计建议,但在这种情况下甚至更重要。 确保首先正确地对并发构造所包装的逻辑进行单元测试。 否则,您可能会花费很长时间尝试找出一个并发问题,最终发现这是有缺陷的业务逻辑。

了解了这些内容之后,您就可以考虑测试并发系统的策略。 GOOS涵盖了您如何做到的。 在这里,您可以找到我将要解释的代码:

首先,让我们看一下被测系统:

public class AtomicBigCounter {private BigInteger count = BigInteger.ZERO;public BigInteger count() {return count;}public void inc() {count = count.add(BigInteger.ONE);}}

如您所见,该类不是线程安全的,因为它通过inc()方法公开了一些状态。 状态不是线程安全的(您可以使用AtomicInteger而不是BigInteger进行修复)。 为了测试该类,我们将包括一个非并行和并行测试。

@Test public void canIncreaseCounter(){...}@Test public void canIncrementCounterFromMultipleThreadsSimultaneously()throws  InterruptedException {MultithreadedStressTester stressTester = new MultithreadedStressTester(25000);stressTester.stress(new Runnable() {public void run() {counter.inc();}});stressTester.shutdown();assertThat("final count", counter.count(),equalTo(BigInteger.valueOf(stressTester.totalActionCount())));}

压力测试仪将使用m个线程执行n个循环的方法。 随着我们的方法递增1,我们应该看到n*m等于counter.count()

有趣的类是MultithreadedStressTester:

public void stress(final Runnable action) throws InterruptedException {spawnThreads(action).await();}private CountDownLatch spawnThreads(final Runnable action) {final CountDownLatch finished = new CountDownLatch(threadCount);for (int i = 0; i < threadCount; i++) {executor.execute(new Runnable() {public void run() {try {repeat(action);}finally {finished.countDown();}}});}return finished;}private void repeat(Runnable action) {for (int i = 0; i < iterationCount; i++) {action.run();}}

如果执行该测试,您将收到不同的结果,有时甚至会通过! 那是因为该测试不是确定性的,所以我们无法确保线程在每次执行中如何交错。 如果我们希望尽可能确保此测试找到可能的错误,则应增加线程和迭代的数量,但要权衡时间。

您可以使用Weaver使用更具确定性的方法。 为了理解它是如何工作的,让我们用一个例子来说明它。 假设我们有一个内存中而不是线程安全的存储:

private final Map<Level, Scores> scoresByLevel;

我们有一些服务可以访问包装该存储库的存储库:

1 Optional<Scores> scoresFromStore = scoreRepo.findBy(score.level());2       if(scoresFromStore.isPresent()) {3          scoreRepo.update(score.level(), score);4       } else {5          scoreRepo.save(score.level(), new Scores().add(score));6       }

该服务位于服务器中,是一个单例,每个请求都会生成一个线程,因此我们希望自动执行该部分。 我们可以使用压力测试非确定性方法,也可以使用Weaver。 如果我们对这个问题进行深入思考,我们就会意识到我们要测试以下各项的每个组合(例如,线程1在x时刻执行第1行,线程2在x时刻执行第1行,将是-> T1 / 1: T2 / 1)

  • T1 / 1:T2 / 1
  • T1 / 1:T2 / 2
  • T1 / 1:T2 / 3
  • …。
  • T1 / 2:T2 / 1
  • T1 / 2:T2 / 2
  • T1 / 2:T2 / 3
  • …。

例如,如果T1 / 5和T2 / 2尚未保存,而T2已经从商店中获得了空分,那么我们将遇到问题。 这意味着T1将得分保存在一个级别中,然后T2将这样做,从而破坏了逻辑。 这正是Weaver所做的,它获取一个方法并使用两个线程执行上述组合。

如果我删除了准备代码(用@ThreadedBefore注释),则测试代码将如下所示:

@ThreadedMainpublic void mainThread() {scoreService.save(LEVEL_ID, SCORE_VALUE, aUser);}@ThreadedSecondarypublic void secondThread() {scoreService.save(LEVEL_ID, ANOTHER_SCORE_VALUE, aUser);}@ThreadedAfterpublic void after() {Optional<Scores> scores = scoreRepo.findBy(aLevel());assertThat(scores.isPresent()).isTrue();assertThat(scores.get().contains(aScoreWith(aUser))).isTrue();assertThat(scores.get().contains(aDifferentScoreWith(aUser))).isTrue();}@Testpublic void testThreading() {new AnnotatedTestRunner().runTests(this.getClass(), ScoreService.class);}

由于确定性,该测试将始终失败。 如您所见,测试并发性非常困难,这就是为什么我支持现代框架的原因,这些框架试图将麻烦隐藏在平台中或通过不可变数据解决问题。

  • 您可以在此处了解更多信息。

翻译自: https://www.javacodegeeks.com/2015/12/testing-multithreaded-code-java.html

用Java测试多线程代码相关推荐

  1. java测试性能代码_关于性能:Java代码内部的基准测试

    我最近一直在研究基准测试,我一直对记录程序数据等感兴趣.我想知道我们是否可以在程序中有效地实现自己的内存使用代码和实现自己的时间消耗代码.我知道如何检查代码运行所需的时间: public static ...

  2. Java接口多线程并发测试 (一)

    本文为作者原创,禁止转载,违者必究法律责任!!! 本文为作者原创,禁止转载,违者必究法律责任!!! Java接口多线程并发测试 一,首先写一个接口post 请求代码: import org.apach ...

  3. apachejmeter_java源码_自定义编写jmeter的Java测试代码

    我们在做性能测试时,有时需要自己编写测试脚本,很多测试工具都支持自定义编写测试脚本,比如LoadRunner就有很多自定义脚本的协议,比如"C Vuser","JavaV ...

  4. flinkCdc的mysql配置及java测试代码

    测试使用的是flinkCdc2.1.1版本(无锁同步,1.x版本有同步锁)目前支持mysql5.7及以上版本; 要在mysql.cnf中配置开启开启mysql的bin-log日志, log_bin=m ...

  5. Java实现多线程远程投屏并打包可执行文件(从代码到.exe)

    Java实现多线程远程投屏并打包可执行文件(从代码到.exe) 前言 原理 成品展示 代码实现 客户端 生成询问框 询问框选择响应 截取输入字符串 与服务端建立联系 创建数据输入流 创建窗口及面板 获 ...

  6. Java中多线程、多线程的实现方式、同步代码块的方式

    多线程 进程 线程 概念 目前的程序是单线程 线程的组成部分 代码实现多线程的方式 第一种方式 第二种方式 第三种方式 -- 线程池 第四种方式:Callable 线程状态 线程同步 临界资源 原子操 ...

  7. jmeter之java代码性能测试_松勤软件性能测试-自定义编写的Java测试代码在Jmeter中如何使用...

    原标题:松勤软件性能测试-自定义编写的Java测试代码在Jmeter中如何使用 我们在做性能测试时,有时需要自己编写测试脚本,很多测试工具都支持自定义编写测试脚本,比如LoadRunner就有很多自定 ...

  8. java实现多线程抢单_Java模拟多线程实现抢票代码实例

    这篇文章主要介绍了Java模拟多线程实现抢票,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 实现100张票抢购的demo 这里需要一个变量,来保存1 ...

  9. [Java] 使用Android Studio编写Java测试代码

    目录 一.创建"Java or Kotlin Library" 模组. 1.1 新建Android Project. 1.2 新建 "Java or Kotlin Lib ...

最新文章

  1. java 数据聚合_Java数据聚合问题请教?
  2. HTML5动态分页效果代码
  3. python爬虫图片-如何用Python来制作简单的爬虫,爬取到你想要的图片
  4. 怎样使用AutoLayOut为UIScrollView添加约束
  5. python:dataframe保存成csv文件和读取
  6. SQL应用与开发:(三)数据操作 #183; 改 AND 删
  7. Xilinx Vivado的使用详细介绍(1):创建工程、编写代码、行为仿真、Testbench
  8. 程序员心声:我为什么偏爱苹果电脑和Mac OS X
  9. 年纪轻轻却突然猝死?数据分析告诉你“猝死”离我们到底有多近?
  10. JS格式化数字保留两位小数点—toFixed()
  11. 首个单芯片超小封装I2C转PWM解决方案
  12. 蓝桥杯2018年第九届C/C++省赛B组第六题-递增三元组
  13. jquery漂浮广告代码
  14. office插件开发_推荐!办公必备,Office插件大合集
  15. 倾斜摄影技术构建 WebGIS 智慧展馆 | 图扑软件
  16. ArcGIS 遥感图像分类—随机树和最大似然分类器
  17. NFT数字艺术品热潮下,IPFS或成为其最佳的存储解决方案
  18. 接口和继承知识点总结
  19. 累加器A用c语言,在c语言数组累加器的使用
  20. Unity 灯光系统详解

热门文章

  1. Tomcat 服务自动启动
  2. 《金色梦乡》金句摘抄(八)
  3. 2017 年编程语言排行榜:Python 排第一
  4. 遍历线索化二叉树+图解
  5. 开发环境 Minio 添加桶的操作流程-页面操作
  6. No primary or default constructor found for interface java.util.List
  7. html5 地图效果,html5 echarts图表插件炫光的分布地图动画特效
  8. linux下单点故障的软件,KeepAlived防止单点故障
  9. vmware安装centos6-步骤小结
  10. java日志——基本日志+高级日志