写在前面的话
本章讲解的主要内容是如何测试并发程序,整体来看是如下几个步骤:
- 先考虑无并发的顺序性执行的正确性
- 对阻塞操作进行测试
- 引入随机进行并发测试其安全性
- 资源管理方面的测试,防止内存不合理占用
- 性能测试
接下来提出了测试中需要关注的一些问题,例如GC,代码动态编译等等。
最末提出了一些补充测试的方法。整体述求还是如何写出正确的并发代码。
测试并发程序
- 安全性测试:验证不变约束
- 活跃度测试:应该“执行”和不应该“执行”
- 性能测试:
- 吞吐量
- 响应性
- 可伸缩性
测试正确性
首先看下测试的基准程序,一个基于数组的定长序列
1 | package javaconcurrency.javatest; |
接下来开始各种测试
基本的单元测试
首先简单的验证下空和满的问题
1 | package javaconcurrency.javatest; |
这种验证是验证顺序化的基本逻辑是否正确。
测试阻塞操作
1 |
|
上述的测试用例测试了阻塞和恢复的情况。先从空的队列中取,这时候就阻塞了操作,最后再恢复。
测试安全性
要构建一个并发类在不可知的并发条件下能否正确执行,只能安排多个线程运行put和take操作
测试应该在多处理器上进行,并且让测试中的线程数大于CPU数。
测试资源管理
需要测试资源用尽的情况。当生产者远多于消费者时就会出现。
对内存不合理的占用,可以通过很多的堆工具测试出来。
使用回调
回调用户提供的代码,有助于创建测试用例。
向线程池提交一些长耗时的任务,可以测试线程池是否如期的增长
产生更多的交替操作
使用thread.yeild或者thread.sleep,产生更多的交替操作。
测试性能
在性能测试中包含一些基本的功能测试,这样可以确保做性能测试的代码都是正确的。
测试响应性
对比多个缓存方案
避免性能测试的陷阱
垃圾回收
垃圾回收是可能对测试造成误差的。
- 确保在整个运行期间都不进行垃圾回收(-verbose:gc)
- 确保垃圾回收再整个运行期间被执行多次
动态编译
抛弃第一组数据