Junit单元测试子线程不执行
环境
- Junit:4
- jdk:1.8
1、现象描述
在测试CountDownLatch类时,使用main函数能够正常运行的功能,改用Junit测试时,Debug调试时不进入子线程执行,直接运行时,有时候能够执行子线程中的部分代码,具体程序如下:
import org.junit.Test;
import java.util.concurrent.CountDownLatch;
/**
* @ClassName: CountDownLatchTest
* @Description: CountDownLatch测试类
* @author Yue Chang
* @date 2018年1月16日 上午11:31:26
* @since 1.0
*/
public class CountDownLatchTest {
@Test
public void test() throws InterruptedException {
CountDownLatch latch = new CountDownLatch(1);
MyThread myThread = new MyThread(latch);
Thread t1 = new Thread(myThread);
t1.setName("t1");
Thread t2 = new Thread(myThread);
t2.setName("t2");
t1.start();
t2.start();
}
public static void main(String[] args) {
CountDownLatch latch = new CountDownLatch(1);
MyThread myThread = new MyThread(latch);
Thread t1 = new Thread(myThread);
t1.setName("t1");
Thread t2 = new Thread(myThread);
t2.setName("t2");
t1.start();
t2.start();
}
}
class MyThread implements Runnable{
private CountDownLatch latch;
private volatile int number;
/**
* @param latch
*/
public MyThread(CountDownLatch latch) {
this.latch = latch;
}
public MyThread() {
}
public CountDownLatch getLatch() {
return latch;
}
public void setLatch(CountDownLatch latch) {
this.latch = latch;
}
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
public void run() {
String threadName = Thread.currentThread().getName().trim();
if ("t2".equals(threadName)) { // t2线程
try {
Thread.sleep(5000);
System.out.println("线程0:" + threadName);
} catch (InterruptedException e) {
e.printStackTrace();
}
this.setNumber(1);
latch.countDown(); // 计数减1
} else if ("t1".equals(threadName)) { // t1线程
try {
System.out.println("线程1:" + threadName);
latch.await(); // 阻塞等待计数为0
System.out.println("线程1:" + threadName);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("num = " + this.getNumber());
}
}
}
2、执行结果
执行Junit结果如下:
线程1:t1
或者是什么都没有打印
执行main结果如下:
线程1:t1
线程0:t2
线程1:t1
num = 1
执行t1时,由于countDownLatch值还不为0,于是将处于等待中,知道t2执行完,将countDownLatch的值减1,变为0时,t1才继续执行,最后打印出num。
3、分析
后面查找资料才知道Junit当主线程退出,子线程也会退出。这样一来也就可以解释为什么有时候执行部分,有时候完全没有执行这个现象了。
4、解决办法:
在Junit测试代码中,加上如下代码:
// junit主线程执行完之后,不会再去管子线程的执行情况,如果没有join(),那么大多数情况下子线程没法执行完
t1.join();
让主线程等待t1线程执行完,也就可以让子线程正常执行了