多线程测试的不确定性
多线程程序的BUG往往具有不确定性,例如可见性问题、死锁、饥饿等问题都不是必然出现的。造成不确定的常见因素包括:
- 程序的执行会交错顺序
- 并发程度的增加可能造成锁泄漏(一个线程在持有一个显式锁的情况下最多可以重复2,147,483,647次申请该锁,超过会抛出Error)
- JIT编译优化造成指令重排序
- 硬件平台本身架构导致的内存重排序
可测试性
提高多线程程序的可测试性可以从以下几个方面入手:
抽象与实现分离
尽量面向接口编程
数据与数据来源分离
例如:由文件输入的数据不要直接使用File或者FileInputStream读取,而是使用InputStream来表示输入源,这样就可以脱离数据的来源进行测试
依赖注入
产生外部对象关联的时候,采用Spring IOC注入对象,或者用Mockito来Mock一个对象
关注点分离
核心功能点仍是按照单线程方式进行单独的单元测试,以确保核心逻辑执行正常。在此基础上,核心功能所涉及到的对象都无须创建具体实例,可以通过创建匿名内部类或匿名内部子类的方式避开核心功能测试,这样可以让我们更加关注对多线程本身的测试
使工作者线程数可以配置
用以排查由并发度造成的问题