《Java并发编程实战》第十二章 测试并发程序 读书笔记
一、正确性測试
import java.util.concurrent.Semaphore;
public class BoundedBuffer<E> {
	private final Semaphore availableItems, availableSpaces;
	private final E[] items;
	private int putPosition = 0;
	private int takePosition = 0;
	@SuppressWarnings("unchecked")
	public BoundedBuffer(int capacity) {
		availableItems = new Semaphore(0);
		availableSpaces = new Semaphore(capacity);
		items = (E[]) new Object[capacity];
	}
	public boolean isEmpty() {
		return availableItems.availablePermits() == 0;
	}
	public boolean isFull() {
		return availableSpaces.availablePermits() == 0;
	}
	public void put(E x) throws InterruptedException {
		availableSpaces.acquire();
		doInsert(x);
		availableItems.release();
	}
	public E take() throws InterruptedException {
		availableItems.acquire();
		E item = doExtract();
		availableSpaces.release();
		return item;
	}
	private synchronized void doInsert(E x) {
		int i = putPosition;
		items[i] = x;
		putPosition = (++i == items.length)?
0 : i;
	}
	private synchronized E doExtract() {
		int i = takePosition;
		E x = items[i];
		items[i] = null;
		takePosition = (++i == items.length)?
0 : i;
		return x;
	}
}
import static org.junit.Assert.*;
import org.junit.Test; public class BoundedBufferTests { @Test
public void testIsEmptyWhenConstructed() {
BoundedBuffer<Integer> bb = new BoundedBuffer<Integer>(10);
assertTrue(bb.isEmpty());
assertFalse(bb.isFull());
} @Test
public void testIsFullAfterPuts() throws InterruptedException {
BoundedBuffer<Integer> bb = new BoundedBuffer<Integer>(10);
for (int i = 0; i < 10; i++) {
bb.put(i);
}
assertTrue(bb.isFull());
assertTrue(bb.isEmpty());
}
}
@Test
public void testTakeBlocksWhenEmpty(){
final BoundedBuffer<Integer> bb = new BoundedBuffer<Integer>(10);
Thread taker = new Thread(){
@Override
public void run() {
try {
int unused = bb.take();
fail(); //假设运行到这里。那么表示出现了一个错误
} catch (InterruptedException e) { }
}
};
try {
taker.start();
Thread.sleep(LOCKUP_DETECT_TIMEOUT);
taker.interrupt();
taker.join(LOCKUP_DETECT_TIMEOUT);
assertFalse(taker.isAlive());
} catch (InterruptedException e) {
fail();
}
}
被堵塞线程并不须要进入WAITING或者TIMED_WAITING等状态,因此JVM能够选择通过自旋等待来实现堵塞。
3 安全性測试
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
import junit.framework.TestCase; public class PutTakeTest extends TestCase {
private static final ExecutorService pool = Executors.newCachedThreadPool();
private final AtomicInteger putSum = new AtomicInteger(0);
private final AtomicInteger takeSum = new AtomicInteger(0);
private final CyclicBarrier barrier;
private final BoundedBuffer<Integer> bb;
private final int nTrials, nPairs; public static void main(String[] args) {
new PutTakeTest(10, 10, 100000).test(); // 演示样例參数
pool.shutdown();
} static int xorShift(int y) {
y ^= (y << 6);
y ^= (y >>> 21);
y ^= (y << 7);
return y;
} public PutTakeTest(int capacity, int nPairs, int nTrials) {
this.bb = new BoundedBuffer<Integer>(capacity);
this.nTrials = nTrials;
this.nPairs = nPairs;
this.barrier = new CyclicBarrier(nPairs * 2 + 1);
} void test() {
try {
for (int i = 0; i < nPairs; i++) {
pool.execute(new Producer());
pool.execute(new Consumer());
}
barrier.await(); // 等待全部的线程就绪
barrier.await(); // 等待全部的线程运行完毕
assertEquals(putSum.get(), takeSum.get());
} catch (Exception e) {
throw new RuntimeException(e);
}
} class Producer implements Runnable {
@Override
public void run() {
try {
int seed = (this.hashCode() ^ (int) System.nanoTime());
int sum = 0;
barrier.await();
for (int i = nTrials; i > 0; --i) {
bb.put(seed);
sum += seed;
seed = xorShift(seed);
}
putSum.getAndAdd(sum);
barrier.await();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
} class Consumer implements Runnable {
@Override
public void run() {
try {
barrier.await();
int sum = 0;
for (int i = nTrials; i > 0; --i) {
sum += bb.take();
}
takeSum.getAndAdd(sum);
barrier.await();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
}
class Big {
	double[] data = new double[100000];
};
void testLeak() throws InterruptedException{
	BoundedBuffer<Big> bb = new BoundedBuffer<Big>(CAPACITY);
	int heapSize1 = /* 生成堆的快照 */;
	for (int i = 0; i < CAPACITY; i++){
		bb.put(new Big());
	}
	for (int i = 0; i < CAPACITY; i++){
		bb.take();
	}
	int heapSize2 = /* 生成堆的快照 */;
	assertTrue(Math.abs(heapSize1 - heapSize2) < THRESHOLD);
}
5 使用回调
6 产生很多其它的交替操作
二、性能測试
1 在PutTakeTest中添加计时功能
this .timer = new BarrierTimer();
this .barrier = new CyclicBarrier(nPairs * 2 + 1, timer); public class BarrierTimer implements Runnable{
private boolean started ;
private long startTime ;
private long endTime ; @Override
public synchronized void run() {
long t = System.nanoTime();
if (!started ){
started = true ;
startTime = t;
} else {
endTime = t;
}
} public synchronized void clear(){
started = false ;
} public synchronized long getTime(){
return endTime - startTime;
}
}
       void test(){
             try {
                   timer.clear();
                   for (int i = 0; i < nPairs; i++){
                         pool .execute( new Producer());
                         pool .execute( new Consumer());
                  }
                   barrier .await();
                   barrier .await();
                   long nsPerItem = timer.getTime() / ( nPairs * (long )nTrials );
                  System. out .println("Throughput: " + nsPerItem + " ns/item");
                  assertEquals(putSum.get(), takeSum.get() )
            } catch (Exception e) {
                   throw new RuntimeException(e);
            }
      }
       public static void main(String[] args) throws InterruptedException {
             int tpt = 100000; // 每一个线程中的測试次数
             for (int cap = 1; cap <= tpt; cap *= 10){
                  System. out .println("Capacity: " + cap);
                   for (int pairs = 1; pairs <= 128; pairs *= 2){
                         TimedPutTakeTest t = new TimedPutTakeTest(cap, pairs, tpt);
                        System. out .println("Pairs: " + pairs + "\t");
                        t.test();
                        System. out .println("\t" );
                        Thread. sleep(1000);
                        t.test();
                        System. out .println();
                        Thread. sleep(1000);
                  }
            }
             pool .shutdown();
      }
2 多种算法的比較
3 响应性衡量
三、避免性能測试的陷阱
1 垃圾回收
2 动态编译
3 对代码路径的不真实採样
4 不真实的竞争程度
5 无用代码的消除
四、其它的測试方法
1 代码审查
2 静态分析工具 
4 分析与监測工具
版权声明:本文博主原创文章,博客,未经同意不得转载。
《Java并发编程实战》第十二章 测试并发程序 读书笔记的更多相关文章
- 《Java并发编程实战》第三章 对象的共享 读书笔记
		
一.可见性 什么是可见性? Java线程安全须要防止某个线程正在使用对象状态而还有一个线程在同一时候改动该状态,并且须要确保当一个线程改动了对象的状态后,其它线程能够看到发生的状态变化. 后者就是可见 ...
 - 《Java并发编程实战》第七章 取消与关闭 读书笔记
		
Java没有提供不论什么机制来安全地(抢占式方法)终止线程,尽管Thread.stop和suspend等方法提供了这种机制,可是因为存在着一些严重的缺陷,因此应该避免使用. 但它提供了中断In ...
 - 《Java并发编程实战》第四章 对象的组合 读书笔记
		
一.设计线程安全的类 在设计线程安全类的过程中,须要包括下面三个基本要素: . 找出构成对象状态的全部变量. . 找出约束状态变量的不变性条件. . 建立对象状态的并发訪问管理策略. 分析对象的 ...
 - 《Java并发编程实战》第十章 避免活跃性危急 读书笔记
		
版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/love_world_/article/details/27635333 一.死锁 所谓死锁: 是指两 ...
 - 《Java并发编程实战》第八章 线程池的使用 读书笔记
		
一.在任务与运行策略之间的隐性解耦 有些类型的任务须要明白地指定运行策略,包含: . 依赖性任务.依赖关系对运行策略造成约束.须要注意活跃性问题. 要求线程池足够大,确保任务都能放入. . 使用线程封 ...
 - 并发编程从零开始(十二)-Lock与Condition
		
并发编程从零开始(十二)-Lock与Condition 8 Lock与Condition 8.1 互斥锁 8.1.1 锁的可重入性 "可重入锁"是指当一个线程调用 object.l ...
 - 【Java并发编程实战】----- AQS(二):获取锁、释放锁
		
上篇博客稍微介绍了一下AQS,下面我们来关注下AQS的所获取和锁释放. AQS锁获取 AQS包含如下几个方法: acquire(int arg):以独占模式获取对象,忽略中断. acquireInte ...
 - 《Java并发编程实战》第六章 任务运行 读书笔记
		
一. 在线程中运行任务 无限制创建线程的不足 .线程生命周期的开销很高 .资源消耗 .稳定性 二.Executor框架 Executor基于生产者-消费者模式.提交任务的操作相当于生产者.运行任务的线 ...
 - 《Java并发编程实战》第十一章 性能与可伸缩性 读书笔记
		
造成开销的操作包含: 1. 线程之间的协调(比如:锁.触发信号以及内存同步等) 2. 添加�的上下文切换 3. 线程的创建和销毁 4. 线程的调度 一.对性能的思考 1 性能与可伸缩性 执行速度涉及下 ...
 
随机推荐
- Android  ServiceManager启动
			
许久就想写篇关于servicemanager的文章,之前对服务启动顺序诸如zygote,systemserver.等启动顺序理解有点混乱,现做例如以下理解分析: 事实上init进程启动后,Servic ...
 - LDD3之并发和竞态-completion(完毕量)的学习和验证
			
LDD3之并发和竞态-completion(完毕量)的学习和验证 首先说下測试环境: Linux2.6.32.2 Mini2440开发板 一開始难以理解书上的书面语言,这里<linux中同步样例 ...
 - RDA安装
			
解压到/home/oracle下面 $ cp /home/oracle/rda $ perl rda.pl -cv 运行上面的命令,如果最后一行出现下面所示,说明没问题 No ...
 - Linux系统编程_8_进程控制之fork_wait_waitpid函数
			
fork函数: #include <unistd.h> pid_t fork(void); fork用来创建一个子进程: 特点: fork调用后会返回两次,子进程返回0,父进 ...
 - JavaScript 初学者应知的 24 条最佳实践
			
原文:24 JavaScript Best Practices for Beginners (注:阅读原文的时候没有注意发布日期,觉得不错就翻译了,翻译到 JSON.parse 那一节觉得有点不对路才 ...
 - Oracle列加密
			
加密函数 create or replace function encrypt_des(p_text varchar2, p_key varchar2) return varchar2 isv_tex ...
 - Django日志器的使用
			
Logging Mudel A quick logging primer Django uses Python’s builtin logging module to perform system l ...
 - 【前端统计图】echarts实现单条折线图
			
五分钟上手: 图片.png <!DOCTYPE html> <html> <head> <meta charset="utf-8"> ...
 - 切换-5.7-传统复制切换成GTID复制
			
1.基本环境: Master Slave MySQL版本 MySQL-5.7.16-X86_64 MySQL-5.7.16-X86_64 IP 192.168.56.156 192.168.5 ...
 - 【codeforces 755B】PolandBall and Game
			
time limit per test1 second memory limit per test256 megabytes inputstandard input outputstandard ou ...