背景
今天写了一个多线程的类,发现测试方法输出的结果并不对; 同样的代码,经过main方法后输出的结果却是正常的;经过研究后发现单元测试@Test并不支持多线程测试;多次运行,其结果要么没有任何输出结果,要么输出不全
原因分析
我们可以看一下TestRunner源码:
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类下的wasSuccessful()方法:
/**
* Returns whether the entire test was successful or not.
*/
public synchronized boolean wasSuccessful() {
return failureCount() == 0 && errorCount() == 0;
}
在这里我们明显可以看到:当aTestRunner调用start方法后不会去等待子线程执行完毕在关闭主线程,而是直接调用TestResult.wasSuccessful()方法,而这个方法始终返回的是false,所以主线程接下来就会执行System.exit,这个放回会结束当前运行的jvm虚拟机,所以使用junit测试多线程方法的结果异常就正常了;
(ps:想要正常输出的话可以让主线程不要结束,等待子线程全部运行结束后在结束主线程,输出结果就会正常,下面会junit测试多线程正常输出的方法:
@Test
public void implRunnable() throws InterruptedException {
ImplRunnable implRunnable = new ImplRunnable();
new Thread(implRunnable, "线程1").start();
new Thread(implRunnable, "线程2").start();
Thread.sleep(100000);
}
在最后价格Thread.sleep()只是为了让主线程等待子线程执行完后在结束,你也可以给你的子线程加线程状态,等待你子线程执行完毕后结束主线程