第八章 Testing Concurrent Applications(测试并发应用)【下】
来源:互联网 发布:通讯录恢复软件 编辑:程序博客网 时间:2024/06/07 14:30
本章涉及内容:
日志:
首先将FindBugs控制窗口打开
日志:
总结:
- 监控Lock接口
- 监控Phaser类
- 监控一个Executor框架
- 监控Fork/Join线程池
- 写有效的日志
- 用FindBugs分析并发代码
- 配置Eclipse调试并发代码
- 用MultithreadTC测试并发代码
1、写有效的日志信息
利用java.util.logging包为你并发应用添加日志信息
package com.jack;import java.util.Date;import java.util.logging.Formatter;import java.util.logging.LogRecord;/** * 定义日志格式 * @author Administrator * */public class MyFormatter extends Formatter{@Overridepublic String format(LogRecord record) {StringBuilder sb = new StringBuilder();sb.append("[" + record.getLevel()+"] -");sb.append(new Date(record.getMillis()) + " : ");sb.append(record.getSourceClassName() + "." + record.getSourceMethodName() + " : ");sb.append(record.getMessage() + "\n");return sb.toString();}}
package com.jack;import java.util.logging.FileHandler;import java.util.logging.Formatter;import java.util.logging.Handler;import java.util.logging.Level;import java.util.logging.Logger;/** * 日志处理器,并将格式设置为自定义格式 * @author Administrator * */public class MyLogger {/** * */private static Handler handler;public static Logger getLogger(String name){Logger logger = Logger.getLogger(name);logger.setLevel(Level.ALL);try {if(handler ==null){handler = new FileHandler("recipe8.log");Formatter format = new MyFormatter();handler.setFormatter(format);}if(logger.getHandlers().length==0){logger.addHandler(handler);}} catch (SecurityException e){e.printStackTrace();} catch (Exception e) {e.printStackTrace();}return logger;}}
package com.jack;import java.util.concurrent.TimeUnit;import java.util.logging.Logger;public class Task implements Runnable{@Overridepublic void run() {Logger logger =MyLogger.getLogger(this.getClass().getName());logger.entering(Thread.currentThread().getName(),"run()");try {TimeUnit.SECONDS.sleep(2);} catch (InterruptedException e){e.printStackTrace();}logger.exiting(Thread.currentThread().getName(), "rum()", Thread.currentThread());}}
package com.jack;import java.util.logging.Level;import java.util.logging.Logger;public class Main {public static void main(String[] args) throws Exception{Logger logger = MyLogger.getLogger("Core");logger.entering("Core", "Main()", args);Thread threads[] = new Thread[5];for (int i=0; i<threads.length; i++){logger.log(Level.INFO, "启动线程:" + i);Task task = new Task();threads[i] = new Thread(task);logger.log(Level.INFO, "线程创建:"+ threads[i].getName());threads[i].start();}logger.log(Level.INFO, "十个线程已经创建"+" 等待它们完成");for (int i=0; i<threads.length; i++){try {threads[i].join();logger.log(Level.INFO, "线程已经完成了"+threads[i]);} catch (InterruptedException e){logger.log(Level.SEVERE, "Exception", e);}}logger.exiting("Core", "main");}}
日志:
扩展:
- getLevel() : 返回消息级别
- getMIllis() 返回一个信息发给日志对象的日期
- getSourceClassName() : 返回发给日志对象的类名
- getSourceMessageName(): 返回一个发送消息的方法名
- getMessage() : 返回日志消息
- entering() : 用FINER级别写入信息,表明一个方法已经执行
- exiting(): 用FINER级别写入信息,表明一个方法已经结束
- log() : 采用特定的级别写入信息。
写日志注意两点:
- 1、写必要日志信息
- 2、日志必须有对应的级别
2、采用FindBugs分析并发代码
检查bug 的工具有Checkstyle, PMD , 或FindBug
FindBugs有独立程序,也有eclipse插件,咱们采用eclipse插件、
首先安装FindBugs插件
安装后重启eclipse
写代码:
package com.jack;import java.util.concurrent.TimeUnit;import java.util.concurrent.locks.ReentrantLock;public class Task implements Runnable{private ReentrantLock lock;public Task(ReentrantLock lock) {super();this.lock = lock;}@Overridepublic void run() {lock.lock();try{TimeUnit.SECONDS.sleep(1);lock.unlock();} catch (InterruptedException e){e.printStackTrace();}}}
package com.jack;import java.util.concurrent.locks.ReentrantLock;import java.util.logging.Level;import java.util.logging.Logger;public class Main {public static void main(String[] args) throws Exception{ReentrantLock lock = new ReentrantLock();int num=1;for (int i=0; i<10; i++){Task task = new Task(lock);Thread thread = new Thread(task);thread.run();}if(num!=1) {System.out.printf("不会进入");}//运行时异常它不会检测出来的,所以是静态的int i = 1/0;System.out.println(i);}}
首先将FindBugs控制窗口打开
最后的效果是:
运行:
效果:
3、配置eclipse调试并发代码
这样你就可以调试某个线程的执行。
4、采用MultithreadedTC 测试并发代码
MultithreadedTC 是用来测试并发应用的jar库,它目的就是解决多线程执行的不确定性。你不能控制执行顺序,为了这个目的,它内部一个节拍器去控制不同线程的执行顺序。
例子:将会学习用MultithreadedTC测试LinkedTransferQueue。
下载googlejar :MultithreadedTC
下载JUnit 4.1 :JUnit 4.1
然后添加到类路径上。(buildpath)
如果是maven工程:添加依赖
<dependency><groupId>com.googlecode.multithreadedtc</groupId><artifactId>multithreadedtc</artifactId><version>1.01</version><scope>test</scope></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.1</version><scope>test</scope></dependency>
package learn;import java.util.concurrent.LinkedTransferQueue;import edu.umd.cs.mtc.MultithreadedTestCase;public class ProducerConsumerTest extends MultithreadedTestCase{private LinkedTransferQueue<String> queue;@Overridepublic void initialize() {super.initialize();queue = new LinkedTransferQueue<String>();System.out.printf("测试:测试已经初始化了\n");}public void thread1() throws InterruptedException {String ret = queue.take();System.out.printf("线程1: %s\n", ret);}public void thread2() throws InterruptedException {waitForTick(1);String ret = queue.take();System.out.printf("线程2 : %s \n", ret);}public void thread3() throws InterruptedException {waitForTick(1);waitForTick(2);queue.put("事件1");queue.put("事件2");System.out.printf("线程3: 插入两个元素\n");}public void finish(){super.finish();System.out.printf("测试:结束\n");assertEquals(true, queue.size()==0);System.out.printf("测试:结果:这个队列已经空了\n");}}
package learn;import edu.umd.cs.mtc.TestFramework;public class Main {public static void main(String[] args) throws Throwable{ProducerConsumerTest test = new ProducerConsumerTest();System.out.printf("Main: 开始测试\n");TestFramework.runOnce(test);System.out.printf("Main 测试已经完成\n");}}
日志:
Main: 开始测试测试:测试已经初始化了线程3: 插入两个元素线程1: 事件1线程2 : 事件2 测试:结束测试:结果:这个队列已经空了Main 测试已经完成
总结:
- 1、initialize():初始化
- 2、finish(): 执行结束,可以做一些释放资源的事情
- 3、waitForTick() : 控制执行顺序
全书已经完了。。。。
阅读全文
0 0
- 第八章 Testing Concurrent Applications(测试并发应用)【下】
- 第八章 Testing Concurrent Applications(测试并发应用)【上】
- 第六章 Concurrent Collections (并发集合类) 【下】
- Penetration Testing : Applications
- Java Concurrent包下的并发容器
- 并发Concurrent
- Java7并发编程指南——第八章:测试并发应用程序
- 第十二章 测试(Testing)
- java concurrent下BlockQueue阻塞队列应用
- JDK 1.5 使用java.util.concurrent开发并发应用
- JDK 1.5 使用java.util.concurrent 开发并发应用
- Java并发包Concurrent下Callable和Future实战
- Concurrent应用
- Web Testing: Complete guide on testing web applications
- Concurrent(并发)
- Concurrent Collections 并发集合
- concurrent并发包结构
- Guava ---- Concurrent并发
- 《Win32多线程程序设计》之线程优先级
- hdu 6171 Admiral 双向bfs+hash
- java每日一练
- 2017年8月24日训练日记
- 欢迎使用CSDN-markdown编辑器
- 第八章 Testing Concurrent Applications(测试并发应用)【下】
- HDU 6180 贪心记录
- OS逆向之二--逆向技术基本操作(未完成)
- JavaScript学习(二) 运算符
- 批量修改文件名
- My97DatePicker的简单使用
- 欢迎使用CSDN-markdown编辑器
- HDU 3695 Computer Virus on Planet Pandora and HDU 2896 病毒侵袭(AC自动机裸题)
- 在eclipse中修改spark2.1源码