用Java测试多线程代码

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

了解了这些内容之后,您就可以考虑测试并发系统的策略。 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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/356093.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

php pdo mysql query_PHP+MYSQL中使用PDO的query方法

一 代码class"php">PDO连接MySQL数据库IDPDO数据库时间$dbmsmysql; //数据库类型 ,对于开发者来说&#xff0c;使用不同的数据库&#xff0c;只要改这个&#xff0c;不用记住那么多的函数$hostlocalhost; //数据库主机名$dbNamedb_database15; //使用的数据库$use…

java 冒号 正则表达式_Java正则表达式问号冒号的使用

在Java和Javascript中正则表达式字符串前面加上?:表示非捕获型匹配&#xff0c;否则就是捕获型匹配。捕获型括号会将匹配到的内容捕获到一些变量里&#xff0c;这些变量按照捕获型括号的左括号为顺序从1开始编号。为了避免括号太多使编号混乱&#xff0c;也为了避免无用的捕获…

Hibernate中的一对多XML映射

一对多关系指出一个实体的单个实例与另一个实体的多个实例相关联。 换句话说&#xff0c;一个表中的每个记录与另一个表中的多个记录相关联。 让我们看看如何通过XML映射文件在Hibernate中定义这种关系。 1.实体关系图 假设我们已经在数据库中创建了学生表和部门表&#xff0…

camel eip_Apache Camel教程– EIP,路由,组件,测试和其他概念的简介

camel eip公司之间的数据交换增加了很多。 必须集成的应用程序数量也增加了。 这些接口使用不同的技术&#xff0c;协议和数据格式。 但是&#xff0c;这些应用程序的集成应以标准化的方式建模&#xff0c;有效实现并由自动测试支持。 企业集成模式&#xff08;EIP&#xff09;…

JavaOne和OOW 2015总结

大家好&#xff01; 终于&#xff0c;我回来了一个很棒的JavaOne和OOW2015。在这篇文章中&#xff0c;我想分享我的经验&#xff0c;一些照片和我参加的演讲的摘要。 会议前 我于2015年6月24日星期六乘Copa航空公司CLO-PTY-SFO飞往旧金山。 从哥伦比亚出发&#xff08;大约8小…

Marin说PCB之 PCB封装和原理图封装的藕断丝连--续集(2)

最近天气越来越冷了&#xff0c;小编我在上海漂泊的十多年了&#xff0c;感觉今年似乎是最冷的一年啊。家里的秋裤都不管用了&#xff0c;要换成大棉裤和军大衣啊。而且现在羽绒服大部分都很贵&#xff0c;动不动上千元了&#xff0c;都赶得上小编我几个月的私房钱了都&#xf…

调整线程池的重要性

无论您是否知道&#xff0c;您的Java Web应用程序很可能都使用线程池来处理传入的请求。 这是许多人忽略的实现细节&#xff0c;但是迟早您需要了解如何使用该池以及如何为您的应用程序正确调整池。 本文旨在说明线程模型&#xff0c;什么是线程池以及正确配置线程池所需执行的…

在线原理图绘制网站推荐

如今专业EDA软件已经基本在硬件公司普及并正版化&#xff0c;优秀的EDA工具包括 Cadence公司的OrCAD、Allegro软件&#xff0c;Mentor Graphics的PADS&#xff0c; Altium公司的Altium Designer等等&#xff0c;但是它们在功能异常强大的同时也在一些时候显得非常复杂&#xff…

java map与set的区别_java 集合(list,set,map)三者之间的关系和区别

原java 集合(list&#xff0c;set&#xff0c;map)三者之间的关系和区别一&#xff1a;先上一张关系图&#xff0c;让大家看的更明白。备注&#xff1a;其中红色部分为实现&#xff0c;其他地方均为接口。二&#xff1a;各自的特点。List 有序,可重复ArrayList优点: 底层数据结…

adf时间作用域_ADF任务流:页面片段的托管bean作用域

adf时间作用域介绍 当我们使用ADF任务流并需要实现一些特定于流的业务逻辑或存储一些与流相关的信息时&#xff0c;我们通常使用pageFlowScope托管bean。 而且&#xff0c;当我们需要为流的活动&#xff08;页面或页面片段&#xff09;提供服务时&#xff0c;我们会为此类托管b…

IMA文件如何打开,winimage使用方

一般先用UltraISO打开一个系统的镜像文件&#xff08;.iso&#xff09;。其中有些文件&#xff08;尤其是.ima,img&#xff09;比如下面雨林木风Ghost系统盘的这个IMA文件&#xff0c;我们先提取到桌面 用WinImage打开这个文件即可发现这个IMA文件整合了很多东西。所以&#x…

Java的几何布朗运动

Wiener过程是连续时间随机过程&#xff0c;以纪念Norbert Wiener命名。 通常用于用随机成分表示噪音或财务状况。 可以计算几何布朗运动以可视化某些界限&#xff08;以分位数表示&#xff09;以暗示绝对范围。 为了进行计算&#xff0c;需要以下参数&#xff1a; &#xff0…

mongodb java id 查询数据_java 用 _id 查找 MongoDB 下的数据

找网上的资料看了下增删改查&#xff0c;等日后补上。已经实现了数据的插入&#xff0c;现在想通过 _id属性来查找数据。一开始看到 类似 55b321df715cc162076eb466 这么一长串的内容觉得是string类型。但是发现并不能搜索到结果&#xff0c;在网上搜到了解决方案&#xff1a;S…

java maven部署_eclipse中maven项目部署到tomcat

下面就一一介绍这几种部署方式&#xff1a;1.打war包到tomcat/webapps目录这种方式其实跟非maven项目没什么区别&#xff0c;就是打包的方式不同之后在target目录下会生成war包&#xff0c;复制到tomcat/webapps目录即完成部署。2.使用tomcat-maven插件&#xff0c;在pom.xml的…

word 论文排版 —— 按指定格式章节的自动编号

在word中如何实现章节标题自动编号 标题样式与标题的编号是两个步骤&#xff0c;为标题建立编号是在为标题样式确定的基础后进行的。这是显而易见的&#xff0c;也即只有先定义了多级标题&#xff08;也可使用 word 自带的标题样式&#xff09;&#xff0c;才可为这些多级标题自…

北斗有 35 颗卫星,而 GPS 有 24 颗卫星,为什么二者数量不同?

作者&#xff1a;知乎用户链接&#xff1a;https://www.zhihu.com/question/21092045/answer/17164418来源&#xff1a;知乎著作权归作者所有。商业转载请联系作者获得授权&#xff0c;非商业转载请注明出处。反对目前的两个不靠谱回答&#xff01;需要的卫星数目和别人占坑没有…

sharesdk短信验证码的集成

在ShareSDK官网http://mob.com/注册并创建Android应用.申请APP_key,下载SDK等 根据官网开发文档导入SDK,目录结构如下 将以上文件按需放入Android Studio项目所要使用SMSSDK的Module所在的Libs里面&#xff0c;再在Module的build.gradle里面将libs加入仓库&#xff08;reposito…

java四神兽_SpringCloud五大神兽之Eureka

注册中心概述什么是注册中心&#xff1f;相当于服务之间的‘通讯录’&#xff0c;记录了服务和服务地址之间的映射关系。在分布式架构中服务会注册到这里。当服务需要调用其他服务时&#xff0c;就在注册中心找到其他服务的地址&#xff0c;进行调用注册中心的主要作用&#xf…

windows下dubbo-admin和zookeeper安装部署

1. 概述 ZooKeeper是Hadoop的正式子项目&#xff0c;它是一个针对大型分布式系统的可靠协调系统&#xff0c;提供的功能包括&#xff1a;配置维护、名字服务、分布式同步、组服务等。ZooKeeper的目标就是封装好复杂易出错的关键服务&#xff0c;将简单易用的接口和性能高效、…

jpush java api_JPush極光推送Java服務器端API

產品功能說明極光推送(JPush)是一個端到端的推送服務&#xff0c;使得服務器端消息能夠及時地推送到終端用戶手機上&#xff0c;讓開發者積極地保持與用戶的連接&#xff0c;從而提高用戶活躍度、提高應用的留存率。極光推送客戶端支持 Android, iOS 兩個平台。本 Android SDK …