今天下午很快完成了一个接口的监控功能,而后屁颠屁颠地用Junit开始单元测试。而后我就开始陷入崩溃的边缘...java
监控结束后须要将监控结果以邮件的形式发送给运营的小伙伴维护,前面测试仍是很顺利,到了开多线程发邮件时就不行了,多线程
程序也不报错,也接收不到邮件。而后改代码再测试,再冥思一下子,再改再测试,仍是无果,最后选择度娘一下,结论是:jvm
Junit单元测试不支持多线程ide
而后,整我的都很差了...浪费了我好多时间,就是由于这个!!!工具
虽然知道告终果,可是笔者仍是须要亲自验证一下。单元测试
/** * @Title: TestDoWork.java * @Describe: * @author: Mr.Yanphet * @Email: mr_yanphet@163.com * @date: 2016年8月15日 下午5:50:03 * @version: 1.0 */ public class TestDoWork { class DoWork implements Runnable { @Override public void run() { for (int i = 0; i < 10000; i++) { long milliSecond = System.currentTimeMillis(); System.out.println("i=" + i + ",milliSecond=" + milliSecond);// 输出循环次数和当前的系统时间 } } } @Test public void test() { DoWork dw = new DoWork(); Thread t = new Thread(dw); t.start(); } }
输出结果以下(笔者省略了部分输出):测试
..... i=751,milliSecond=1471257586416 i=752,milliSecond=1471257586416 i=753,milliSecond=1471257586416 i=754,milliSecond=1471257586416 i=755,milliSecond=1471257586416 i=756,milliSecond=1471257586416 i=757,milliSecond=1471257586416 i=758,milliSecond=1471257586416
从结果能够看到,循环到了759次后就没再输出了,说明子线程还没结束任务,整个程序就被强迫结束了。spa
既然知道了现象,那么为何会出现这样的现象呢,贴出部分Junit4 TestRunner源码就知道了线程
public static final int SUCCESS_EXIT = 0; public static final int FAILURE_EXIT = 1; public static final int EXCEPTION_EXIT = 2; public static void main(String args[]) { TestRunner aTestRunner = new TestRunner(); try { TestResult r = aTestRunner.start(args); if (!r.wasSuccessful()) System.exit(FAILURE_EXIT); System.exit(SUCCESS_EXIT); } catch (Exception e) { System.err.println(e.getMessage()); System.exit(EXCEPTION_EXIT); }
}
再贴上TestResult部分源码,以供参考code
protected List<TestFailure> fFailures protected List<TestFailure> fErrors public synchronized boolean wasSuccessful() { return failureCount() == 0 && errorCount() == 0; } public synchronized int errorCount() { return fErrors.size(); } public synchronized int failureCount() { return fFailures.size(); }
在TestRunner中能够看出,若是是单线程,当测试主线程执行结束后,无论子线程是否结束,都会回调TestResult的wasSuccessful方法,
而后判断结果是成功仍是失败,最后调用相应的System.exit()方法。你们都知道这个方法是用来结束当前正在运行中的java虚拟机,jvm都自身难保了,因此子线程也就对不住你咧...
解决办法:
1 简单粗暴地让主线程休眠一段时间,而后让子线程可以运行结束。可是这个方法的弊端是,你不知道子线程的运行时间,因此须要看脸=_=
Thread.sleep();
2 使用CountDownLatch工具类,让主线程阻塞,直到子线程运行结束或者阻塞超时,这个方法要比第一个方法好点。
countDownLatch.await(5, TimeUnit.MINUTES);
至于还有其余方法,笔者看到不少大神本身写的Junit支持多线程,有兴趣的读者自行度娘...