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

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

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

一、正确性测试

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

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. IP分片(IP Fragment)

    为什么要分片 不同的链路类型能够支持的最大传输单元值(MTU: Maxitum Transmission Unit)主要是由相关RFC文档规定的,常见的以太网链路的MTU值为1500,如果需要转发的I ...

  2. 2018 Multi-University Training Contest 6-oval-and-rectangle(hdu 6362)-题解

    一.题意 求椭圆内接矩形周长的期望. 二.推导过程 已知$c$,容易得出矩形弦长$d=4a\sqrt{1-\frac{c^2}{b^2}}$ 接下来,矩形周长$p=4c+d=4c+4a\sqrt{1- ...

  3. 关于常见的协议BSD,APACHE,MIT,GPL的理解

    其实BSD和APACHE和MIT协议类似,基本就是可以为所欲为,但是要尊重原来的作者. GPL协议是一个免费和开源的协议,只要用了GPL协议的类库源码等,也必须适应GPL协议. 意思就是把开源和免费进 ...

  4. 用VB6.0实现串口通信

    Then       ' 1位或2位          'byte 类型取值范围为 0-255 ,不能为-1                   = ) & )     End IfstrHe ...

  5. Luajit-2.1.0-beta1的发布和生成arm64用bytecode的解脱

    前情提要:由于苹果要求2015年2月1日上架的新app必须支持64位的arm64,旧的app也得在6月1日支持64位,来源.于是unity3d弄出了il2cpp这种花式的玩法来进行64位支持,而对于当 ...

  6. java中将数字的字符串表示转化为数字

    int a = new Integer("1234").intValue() 或 int b = Integer.parseInt("1234") System ...

  7. R_CNN

    https://blog.csdn.net/briblue/article/details/82012575 背景本篇论文的题目是 <Rich feature hierarchies for a ...

  8. 90. Subsets II (Back-Track, DP)

    Given a collection of integers that might contain duplicates, nums, return all possible subsets. Not ...

  9. 【总结整理】关于挪车和虚拟号的思考-转载v2ex

    https://www.baidu.com/link?url=A7wiF1JpOkT6Juo0nNHKcum0OiQsnRj-EZkQfjc3xB-noUeLy3HEY-4plbFmPmuJ& ...

  10. input实时监听控制输入框的输入内容和长度,并进行提示和反馈

    一.前言 在MVVM模式下,有个双向数据绑定(data-binding)的优势,可以通过viewmodel实时的监听用户操作,也可以将model的改动实时的反馈到界面上. 那么,在传统的js操控DOM ...