背景:编写Junit测试多线程,线程类的run方法中做了网络请求。
问题:在运行Junit后,jvm自动停止了。debug运行,也没有到线程类的run方法里面。
原因:让我们来看TestRunner类中的main方法
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);
}
}
Test Result 类
public synchronized boolean wasSuccessful() {
return failureCount() == 0 && errorCount() == 0;
}
由以上可知,在执行完主线程后直接判断TestResult类的wasSuccessful()方法,如果返回false,则关闭jvm。
之后做了小的测试,代码如下:
public class JunitAndThread {
@Test
public void testJunitAndThread(){
for (int i = 0; i < 5; i++) {
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("当前线程id:" + Thread.currentThread().getId());
}
}).start();
}
}
}
以上的输出:
当前线程id:11
当前线程id:12
当前线程id:13
当前线程id:14
当前线程id:15
嗯?这不是运行完毕了?那…会不会是之前没运行完毕,是因为线程中的方法没有执行完?验证一下:
把上面的测试类修改:
public class JunitAndThread {
@Test
public void testJunitAndThread(){
for (int i = 0; i < 5; i++) {
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 1000000000; i++) {
}
System.out.println("当前线程id:" + Thread.currentThread().getId());
}
}).start();
}
}
}
输出结果:
Process finished with exit code 0
嗯,果然是这样。
解决办法1:既然是子线程没执行完,我们可以让主线程等等子线程
public class JunitAndThread {
@Test
public void testJunitAndThread(){
for (int i = 0; i < 5; i++) {
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 1000000000; i++) {
}
System.out.println("当前线程id:" + Thread.currentThread().getId());
}
}).start();
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
输出结果:
当前线程id:14
当前线程id:12
当前线程id:15
当前线程id:13
当前线程id:11Process finished with exit code 0
解决办法2:使用CountDownLatch(统计计数器)
没执行完一条线程后,计数器就会减1,主线程会调用await()方法会进入等待状态,当计数器减为0的时候执行
public class JunitAndCountDownLatch {
private CountDownLatch countDownLatch = new CountDownLatch(5);
@Test
public void testCountDownLatch(){
for (int i = 0; i < 5; i++) {
new Thread(new Runnable() {
@Override
public void run() {
System.out.println(
"当前线程: " +
Thread.currentThread().getId() +
", 当前线程名称: " +
Thread.currentThread().getName()
);
countDownLatch.countDown();
}
},"统计计数器————多线程测试").start();
}
try {
countDownLatch.await(); //主线程等待
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
总结:Junit测试多线程中,主线程不会等待子线程全部执行完然后exit。
网友评论