并发程序中潜在错误的发生并不具有确定性,而是随机的。

安全性测试:通常会采用测试不变性条件的形式,即判断某个类的行为是否与其规范保持一致

活跃性测试:进展测试和无进展测试两方面,这些都是很难量化的(性能:即吞吐量,响应性,可伸缩性测试)

一、正确性测试

重点:找出需要检查的不变性条件和后验条件

1、对基本单元的测试——串行的执行

 1 public class BoundedBufferTests {
2
3 @Test
4 public void testIsEmptyWhenConstructed(){
5 BoundedBuffer<String> bf = new BoundedBuffer<String>(10);
6 assertTrue(bf.isEmpty());
7 }
8
9 @Test
10 public void testIsFullAfterPuts() throws InterruptedException{
11 BoundedBuffer<String> bf = new BoundedBuffer<String>(10);
12 for (int i=0; i<10; i++){
13 bf.put("" + i);
14 }
15 assertTrue(bf.isFull());
16 assertTrue(bf.isEmpty());
17 }
18 }

2、对阻塞操作的测试

  每个测试必须等他创建的所有线程结束后才可以结束(join)

  要测试一个方法的阻塞行为,类似于测试一个抛出异常的方法:如果这个方法可以正常返回,那么就意味着测试失败。

  在测试方法的阻塞行为时,将引入额外的复杂性:当方法被成功地阻塞后,还必须使方法解除阻塞。(中断)

 1 public void testTaskBlocksWhenEmpty(){
2 final BoundedBuffer<Integer> bb = new BoundedBuffer<>(10);
3 Thread taker = new Thread(){
4 @Override
5 public void run() {
6 try {
7 int unused = bb.take();
8 fail(); //不应执行到这里
9 } catch (InterruptedException e) {
10 }
11 }
12 };
13 try {
14 taker.start();
15 Thread.sleep(1000);
16 taker.interrupt();
17 taker.join(2000); //保证即使taker永久阻塞也能返回
18 assertFalse(taker.isAlive());
19 } catch (InterruptedException e) {
20 fail();
21 }
22 }

3、安全性测试

  构建对并发类的安全性测试中,需要解决的关键问题在于,要找出那些容易检查的属性,这些属性在发生错误的情况下极有可能失败,同时又不会使得错误检查代码人为地限制并发性。理想的情况是,在测试属性中不需要任何同步机制

例:通过计算入列和出列的校验和进行检验(使用栅栏保证线程均运行到可检验处再检验)

4、资源管理测试

对于任何持有或管理其他对象的对象,都应该在不需要这些对象时销毁对它们的引用

例:使用堆检验工具对内存资源使用进行检验

5、使用回调

可以通过自定义扩展类来进行相关测试

 1 public class TestingThreadFactory implements ThreadFactory {
2 public final AtomicInteger numCreated =
3 new AtomicInteger(); //记录创建的线程数
4 private final ThreadFactory factory =
5 Executors.defaultThreadFactory();
6
7 @Override
8 public Thread newThread(Runnable r) {
9 numCreated.incrementAndGet();
10 return factory.newThread(r);
11 }
12 }

6、产生更多的交替操作

使用yield、sleep命令更容易使错误出现

二、性能测试

性能测试的目标:

  • 衡量典型测试用例中的端到端性能,获得合理的使用场景
  • 根据经验值来调整各种不同的限值,如线程数量,缓存容量等

1、计时器

通过增加计时器,并改变各个参数、线程池大小、缓存大小,计算出运行时间

例:

2、多种算法的比较

使用不同的内部实现算法,找出具有更高的可伸缩性的算法

例:

3、响应性衡量

某个动作经过多长时间才能执行完成,这时就要测量服务时间的变化情况

除非线程由于密集的同步需求而被持续的阻塞,否则非公平的信号量通常能实现更好的吞吐量,而公平的信号量则实现更低的变动性(公平性开销主要由于线程阻塞所引起)

三、避免性能测试的陷阱

1、垃圾回收

  • 保证垃圾回收在执行测试程序期间不被执行,可通过-verbose:gc查看垃圾回收信息。
  • 保证垃圾回收在执行测试程序期间执行多次,可以充分反映出运行期间的内存分配和垃圾回收等开销。

2、动态编译

  • 可以让测试程序运行足够长时间,防止动态编译对测试结果产生的偏差。
  • 在HotSpot中设置-xx:+PrintCompilation,在动态编译时输出一条信息

3、对代码路径不真实采样

  • 动态编译可能会让不同地方调用的同一方法生成的代码不同
  • 测试程序不仅要大致判断某个典型应用程序的使用模式,还要尽量覆盖在该应用程序中将执行的代码路径集合

4、不真实的竞争程度

  • 不同的共享数据和执行本地计算的比例,将表现出不同的竞争程度,也就有不同的性能和可伸缩性

5、无用代码的消除

  • 编译器可能会删除那些没有意义或不会产生结果或可预测结果的代码
  • 使结果尽量是不可预测的

四、其他测试方法

代码审查(人工检查代码),竞态分析工具(FindBugs,CheckStyle),面向方面的测试技术,分析与检测工具(jvisualvm)

java并发编程实战:第十二章---并发程序的测试的更多相关文章

  1. 《java并发编程实战》读书笔记9--并发程序的测试

    第12章 并发程序的测试 大致分为两类:安全性测试和活跃性测试 12.1 正确性测试 找出需要检查的不变性条件和后验条件.接下来将构建一组测试用例来测试一个有界缓存.程序清单12-1给出了Bounde ...

  2. [CSAPP笔记][第十二章并发编程]

    第十二章 并发编程 如果逻辑控制流在时间上是重叠,那么它们就是并发的(concurrent).这种常见的现象称为并发(concurrency). 硬件异常处理程序,进程和Unix信号处理程序都是大家熟 ...

  3. CSAPP:第十二章 并发编程

    CSAPP:第十二章 并发编程 12.1 线程执行模型12.2 多线程之间并发通信12.3 其他并发问题   使用应用级并发的应用程序称为并发程序.现代操作系统提供三种基本的构造并发程序的方法: 进程 ...

  4. 并发编程从零开始(十二)-Lock与Condition

    并发编程从零开始(十二)-Lock与Condition 8 Lock与Condition 8.1 互斥锁 8.1.1 锁的可重入性 "可重入锁"是指当一个线程调用 object.l ...

  5. 【Java并发编程实战】----- AQS(二):获取锁、释放锁

    上篇博客稍微介绍了一下AQS,下面我们来关注下AQS的所获取和锁释放. AQS锁获取 AQS包含如下几个方法: acquire(int arg):以独占模式获取对象,忽略中断. acquireInte ...

  6. [笔记][Java7并发编程实战手冊]3.8 并发任务间的数据交换Exchanger

    [笔记][Java7并发编程实战手冊]系列文件夹 简单介绍 Exchanger 是一个同步辅助类.用于两个并发线程之间在一个同步点进行数据交换. 同意两个线程在某一个点进行数据交换. 本章exchan ...

  7. 《Java并发编程实战》第三章 对象的共享 读书笔记

    一.可见性 什么是可见性? Java线程安全须要防止某个线程正在使用对象状态而还有一个线程在同一时候改动该状态,并且须要确保当一个线程改动了对象的状态后,其它线程能够看到发生的状态变化. 后者就是可见 ...

  8. 《Java并发编程实战》第十一章 性能与可伸缩性 读书笔记

    造成开销的操作包含: 1. 线程之间的协调(比如:锁.触发信号以及内存同步等) 2. 添加�的上下文切换 3. 线程的创建和销毁 4. 线程的调度 一.对性能的思考 1 性能与可伸缩性 执行速度涉及下 ...

  9. java并发编程实战:第五章----基础构建模块

    委托是创建线程安全类的一个最有效的策略:只需让现有的线程安全类管理所有的状态即可. 一.同步容器类 1.同步容器类的问题 同步容器类都是线程安全的,容器本身内置的复合操作能够保证原子性,但是当在其上进 ...

  10. Java并发编程实战 读书笔记(二)

    关于发布和逸出 并发编程实践中,this引用逃逸("this"escape)是指对象还没有构造完成,它的this引用就被发布出去了.这是危及到线程安全的,因为其他线程有可能通过这个 ...

随机推荐

  1. 【linux】U盘安装启动出现press the enter key to begin the installation process 就不动弹了

    今天在物理机上安装centOS6.5  64bit 系统的时候,出现了U盘安装启动出现press the enter key to begin the installation process 就不动 ...

  2. 使用SharpZip压缩与解压缩

    使用SharpZip压缩与解压缩 编写人:左丘文 2015-4-11 大家在做项目时,相信会经常性的会遇到要对数据流或dataset byte[] 或文件进行压缩和解压缩,比如:利用webservic ...

  3. Python yield详解***

    yield的英文单词意思是生产,有时候感到非常困惑,一直没弄明白yield的用法. 只是粗略的知道yield可以用来为一个函数返回值塞数据,比如下面的例子: def addlist(alist): f ...

  4. 搜索引擎Lucene之皮毛

    一.Lucene是apache软件基金会4 jakarta项目组的一个子项目,是一个开放源代码的全文检索引擎工具包,但它不是一个完整的全文检索引擎,而是一个全文检索引擎的架构,提供了完整的查询引擎和索 ...

  5. java DecimalFormat类

          今天去面试了,需要上机做题.题目的内容是计算一个货物订单的税费和总价格(包括税费),结果需要精确到两个小数,同时按照如下规则进行处理: 3.01 ——>3.05, 2.48——> ...

  6. Spring MVC的困惑url-pattern /和/*的区别

    今天在写项目时发现一个spring 总是报org.springframework.web.servlet.DispatcherServlet noHandlerFound警告: No mapping ...

  7. ZOJ-3230-Solving the Problems

    /*ZOJ Problem Set - 3230Solving the Problems ------------------------------------------------------- ...

  8. Excel2013复制内容粘贴到刷选的数据表中

    如何将复制内容粘贴到筛选后表格中: 1.需要一个表格:我要把这个表格里姓名列不包含A的项改为另外一个表中的数据列: 2.在姓名右侧插入两列,列A.列B: 3.在列A下第一格输入1,向下序列填充: 4. ...

  9. ES6系列_8之函数和数组

    1.对象的函数解构 ES6为我们提供了这样的解构赋值使在前后端分离时,后端返回来JSON格式的数据,前端可以直接把这个JSON格式数据当作参数,传递到函数内部进行处理.比如: let json = { ...

  10. Visio2013 64位下载安装以及破解激活教程

    特别说明:以下教程如果未能破解激活,请在断网条件下安装破解!!!! 安装: Visio2013 professional版下载地址:https://pan.baidu.com/s/1gzwcGTevV ...