单元测试是不支持多线程的,主线程结束之后,不管子线程有没有结束,都会强制退出。但是我们可以通过控制主线程结束的时间来做多线程测试.
在JUnit的@Test方法中启用多线程,新启动的线程会随着@Test主线程的死亡而死亡!导致没有任何输出
解决方法:
- 在@Test方法中每创建一个线程,就join一下,这样我们新建的线程不死亡,Test主线程也不会死亡。
- 通过主线程休眠足够长的时间来等待子线程执行完,这里需要控制好主线程休眠时间才行。
- 通过CountDownLatch来等待所有子线程执行完毕,才结束主线程。
方法1
@Test
public void testMultiThread(){
Thread thread = new Thread(() -> {
try {
TimeUnit.SECONDS.sleep(3);
System.out.println("子线程执行完毕");
} catch (InterruptedException e) {
e.printStackTrace();
}
});
thread.start();
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("@Test线程执行完毕");
}
输出: 子线程执行完毕
@Test线程执行完毕
可以看到Test线程会在子线程执行完之后再结束。如果有多个子线程,就让每个子线程都join一下,这样Test线程就会等待最后一个子线程结束后再结束。这样的好处是Test线程在子线程结束后就可以结束,缺点是每个线程都要join
方法2
@Test
public void testMultiThread(){
Thread thread = new Thread(() -> {
try {
TimeUnit.SECONDS.sleep(1);
System.out.println("子线程执行完毕");
} catch (InterruptedException e) {
e.printStackTrace();
}
});
thread.start();
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("@Test线程执行完毕");
}
输出:子线程执行完毕
@Test线程执行完毕
优点是简单暴力,缺点也很明显:Test线程睡眠的时间要比子线程的执行时间长。如果不好估算子线程会执行多久还是不要用这种方法了。
方法3
@Test
public void testMultiThread(){
CountDownLatch countDownLatch = new CountDownLatch(2);
Thread thread = new Thread(() -> {
try {
TimeUnit.SECONDS.sleep(1);
System.out.println("子线程1执行完毕");
countDownLatch.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
}
});
Thread thread2 = new Thread(() -> {
try {
TimeUnit.SECONDS.sleep(2);
System.out.println("子线程2执行完毕");
countDownLatch.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
}
});
thread.start();
thread2.start();
try {
countDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("@Test线程执行完毕");
}
输出:子线程1执行完毕
子线程2执行完毕
@Test线程执行完毕
子线程执行完毕,主线程才结束