《java并发编程实战》读书笔记9--并发程序的测试
第12章 并发程序的测试
大致分为两类:安全性测试和活跃性测试
12.1 正确性测试
找出需要检查的不变性条件和后验条件。接下来将构建一组测试用例来测试一个有界缓存。程序清单12-1给出了BoundedBuffer的实现,其中使用Semaphore来实现缓存的有界属性和阻塞行为。
BoundedBuffer实现了一个固定长度的队列,其中定义了可阻塞的put和take方法,并通过两个计数信号量进行控制。(实际情况中如果需要一个有界缓存,应该直接使用ArrayBlockingQueue或者LinkedBlockingDeque,而不是自己编写)。
12.1.1 基本的单元测试
BoundedBuffer的最基本单元测试类似与在串行上下文中执行的测试。首先创建一个有界缓存,然后调用它的各个方法,并验证它的后验条件和不变性条件。我们很快会想到一些不变性条件:新建立的缓存应该是空的,而不是满的。另一个略显复杂的安全测试是,将N个元素插入到容量为N的缓存中,然后测试缓存是否已经填满。
12.1.2 对阻塞操作的测试
在测试并发的基本属性时,需要引入多个线程。大多数测试框架并不能很好地支持并发性测试。在java.util.concurrent的一致性测试中,一定要将各种故障与特定的测试明确地关联起来。因此JSR 166专家组创建了一个基类,其中定义了一些可以在tearDown期间(主要实现测试完成后的垃圾回收等工作)传递和报告失败信息,并遵循一个约定:每个测试必须等待它锁创建的全部线程结束以后才能完成。
如果某方法需要在某些特定条件下阻塞,那么当测试这种行为时,只有当线程不再继续执行时,测试才是成功的。要测试一个方法的阻塞行为,类似于测试一个抛出异常的方法:如果这个方法可以正常返回,那么就意味着测试失败。在测试方法的阻塞行为时,将引入额外的复杂性:当方法被成功阻塞后,还必须使用方法接触阻塞。实现这个功能的一种简单方式就是使用中断——在一个单独的线程中启动一个阻塞操作。来个例子:
看了后面忘了前面。。。 现在补下之前的一些知识:
(1) 中断是通过调用Thread.interrupt()方法来做的. 这个方法通过修改了被调用线程的中断状态来告知那个线程, 说它被中断了. 对于非阻塞中的线程, 只是改变了中断状态, 即Thread.isInterrupted()将返回true; 对于可取消的阻塞状态中的线程, 比如等待在这些函数上的线程, Thread.sleep(), Object.wait(), Thread.join(), 这个线程收到中断信号后, 会抛出InterruptedException, 同时会把中断状态置回为false.
(2) t.join()方法阻塞调用此方法的线程(calling thread),直到线程t完成,此线程再继续;通常用于在main()主线程内,等待其它线程完成再结束main()主线程
如果take操作由于某种意料之外的原因停滞了,那么支持时限的join方法能够确保测试最终完成。用于验证线程能否在一个条件等待上阻塞的Thread.getState方法并不可靠(详见p208)
12.1.3 安全性测试
上面的几个测试程序无法发现由于数据竞争而引发的错误。要测试在生产者——消费者模式中使用的类,一种有效的方法就是检查被放入队列中和从队列中取出的各个元素。可以通过一个对顺序敏感的校验和计算函数里计算所有入列元素和出列元素的校验和,并进行比较。如果二者相等那么测试就死成功的。如果要将这种方法扩展到多生产者-多消费者模式的情况,就需要对元素入列/出列顺序不敏感的校验和函数,从而在测试程序运行完后,可以将多个校验和以不同的顺序组合起来。(这部分看得各种懵比)
当线程到达栅栏位置时调用栅栏的await方法,这个方法阻塞直到所有线程都达到栅栏的位置。如果所有线程都达到了栅栏的位置,那么栅栏将被打开,所有线程被释放,栅栏将被重置以便下次使用。
12.1.4 资源管理的测试(p212)
12.1.5 使用回调(p213)
12.1.6 产生更多的交替操作(p214)
由于并发代码中的大多数错误都是一些低概率时间,因此在测试并发错误时需要反复地执行多次,所以有时候需要产生更多的交替操作。一种有用的方法是:在访问共享状态的操作中,使用Thread.yield将产生更多的上下文切换。
yield方法会使当前线程从执行状态(运行状态)变为可执行态(就绪状态)。cpu会从众多的可执行态里选择,也就是说,当前也就是刚刚的那个线程还是有可能会被再次执行到的,并不是说一定会执行其他线程而该线程在下一次中不会执行到了。
应该是面向切面的编程好伐,再次吐槽下这本书的翻译质量。
12.2 性能测试(p215)
12.2.1 在PutTakeTest中增加计时功能(p215)
记录整个运行过程的时间,然后除以操作数的量,从而得到每次操作的运行时间。使用一个栅栏动作来测量启动和结束时间:
老实说这部分我看到云里雾里的,不知道是不是翻译的原因(摔锅中...),二周目准备把这本书的英文版拿来看一遍。
12.2.2 多种算法的比较(p217)
12.2.3 响应性衡量(p219)
12.3 避免性能测试的陷阱(p220)
12.3.1 垃圾回收(p220)
垃圾回收的执行时序是无法预测的,因此在执行测试时,垃圾回收器可能在任何时刻运行。
12.3.2 动态编译(p220)
12.3.3 对代码路劲的不真实采样(p222)
12.3.4 不真实的竞争程度(p222)
12.3.5 无用代码的消除(p223)
12.4 其他的测试方法(p224)
总结:这章基本到后面就看不懂了...., 说了很多理论性的东西。其实我一直觉得理论这东西光说没用,要在实践的基础上理解才行。比较推崇先实践后理论的教学方式,而不是先从理论开始。这里再吐槽下这本书的翻译质量,坑啊。
《java并发编程实战》读书笔记9--并发程序的测试的更多相关文章
- Java多线程编程实战读书笔记(一)
多线程的基础概念本人在学习多线程的时候发现一本书——java多线程编程实战指南.整理了一下书中的概念制作成了思维导图的形式.按照书中的章节整理,并添加一些个人的理解.
- Java并发编程实战 读书笔记(一)
最近在看多线程经典书籍Java并发变成实战,很多概念有疑惑,虽然工作中很少用到多线程,但觉得还是自己太弱了.加油.记一些随笔.下面简单介绍一下线程. 一 线程与进程 进程与线程的解释 个人觉 ...
- Java并发编程实战 读书笔记(二)
关于发布和逸出 并发编程实践中,this引用逃逸("this"escape)是指对象还没有构造完成,它的this引用就被发布出去了.这是危及到线程安全的,因为其他线程有可能通过这个 ...
- 《java并发编程实战》笔记
<java并发编程实战>这本书配合并发编程网中的并发系列文章一起看,效果会好很多. 并发系列的文章链接为: Java并发性和多线程介绍目录 建议: <java并发编程实战>第 ...
- Java并发编程实践读书笔记(5) 线程池的使用
Executor与Task的耦合性 1,除非线程池很非常大,否则一个Task不要依赖同一个线程服务中的另外一个Task,因为这样容易造成死锁: 2,线程的执行是并行的,所以在设计Task的时候要考虑到 ...
- Java并发编程艺术读书笔记
1.多线程在CPU切换过程中,由于需要保存线程之前状态和加载新线程状态,成为上下文切换,上下文切换会造成消耗系统内存.所以,可合理控制线程数量. 如何控制: (1)使用ps -ef|grep appn ...
- Java并发编程实践(读书笔记) 任务执行(未完)
任务的定义 大多数并发程序都是围绕任务进行管理的.任务就是抽象和离散的工作单元. 任务的执行策略 1.顺序的执行任务 这种策略的特点是一般只有按顺序处理到来的任务.一次只能处理一个任务,后来其它任 ...
- Java并发编程实践读书笔记(2)多线程基础组件
同步容器 同步容器是指那些对所有的操作都进行加锁(synchronize)的容器.比如Vector.HashTable和Collections.synchronizedXXX返回系列对象: 可以看到, ...
- Java并发编程实践读书笔记(1)线程安全性和对象的共享
2.线程的安全性 2.1什么是线程安全 在多个线程访问的时候,程序还能"正确",那就是线程安全的. 无状态(可以理解为没有字段的类)的对象一定是线程安全的. 2.2 原子性 典型的 ...
随机推荐
- ContestHunter暑假欢乐赛 SRM 02
惨不忍睹 3个小时都干了些什么... 日常按顺序从A题开始(难度居然又不是递增的 第一眼A题就觉得很简单...写到一半才发现woc那是个环.感觉一下子复杂了,按照链的方法扩展的话要特判很多东西... ...
- 跳跃表 https://61mon.com/index.php/archives/222/
跳跃表(英文名:Skip List),于 1990 年 William Pugh 发明,是一个可以在有序元素中实现快速查询的数据结构,其插入,查找,删除操作的平均效率都为 . 跳跃表的整体性能可以和二 ...
- JavaScript对iframe的DOM操作
在IE6.IE7中,我们可以使用 document.frames[ID].document 来访问iframe子窗口中的document对象,可是这是不符合W3C标准的写法,也是IE下独有的方法,在F ...
- JavaScript滚动条的制作
效果演示 这个效果的制作是借助setTimeout的第三个参数.setTimeout/setInterval,这两个函数相信前端开发同学都很熟悉.它们在非IE(6-9)浏览器中还可以如下使用: v ...
- rand、randi和randn的区别?
1,rand 生成均匀分布的伪随机数.分布在(0~1)之间 主要语法:rand(m,n)生成m行n列的均匀分布的伪随机数 rand(m,n,'double')生成指定精度的均匀分布的伪随机数,参数还可 ...
- 牛客328B Rabbit的工作(1)
传送门:https://ac.nowcoder.com/acm/contest/328/B 题意:给你n和k,和一个长度为n的字符串,字符串中的0表示休息,1表示工作,连续工作会损耗连续的体力值,从1 ...
- 组合框控件 -- CComboBox
组合框控件 -- CComboBox 组合框其实就是把一个编辑框和一个列表框组合到了一起,分为三种:简易(Simple)组合框.下拉式(Dropdown)组合框和下拉列表式(Drop List)组合框 ...
- [nginx]proxy_pass&rewrite知识点
While passing request nginx replaces URI part which corresponds to location with one indicated in pr ...
- gps各种地图坐标系转换
原文地址:https://my.oschina.net/fankun2013/blog/338100 地图供应商比较多,产生了许多地图坐标.地图坐标正确转换是个问题.在之前开发地图应用的时候发现从WG ...
- 如何写出高性能DOM?
为什么要写高性能DOM? 一个网站,在页面上承载最多内容的就是DOM,而且无论是我们通过加载JS.加载图片,他们也是通过写HTML标签来实现的.而我们性能优化要做的无非就是几大块: 站点的网络消耗 D ...