写过单元测试的同学应该遇到过这个问题 单元测试中新建的线程 一般都不会被运行 这是因为JUnit在底层实现上是用 System.exit() 退出的
问题原因
查看JUnit4的TestRunner的源码
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 
 | 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);
 }
 }
 
 | 
可以看到 单元测试执行完毕之后 是用 System.exit() 退出的主线程 主线程结束了 其他线程自然被终止了
解决方案
在Java的线程池中 有一个方法 awaitTermination() 可以检测所有线程是否执行完毕 可以通过循环判断来达到防止主线程退出的目的
下面提供一个工具类
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 
 | package pw.yumc.MiaoServer.kits;
 import java.io.File;
 import java.util.concurrent.SynchronousQueue;
 import java.util.concurrent.ThreadFactory;
 import java.util.concurrent.ThreadPoolExecutor;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicInteger;
 
 
 
 
 
 public class ExecutorKit {
 static ExecutorService executor = Executors.newCachedThreadPool();
 
 public static void execute(Runnable run) {
 executor.execute(run);
 }
 
 public static ThreadPoolExecutor getExecutor() {
 return executor;
 }
 
 public static void shutdownAndWait() {
 executor.shutdown();
 boolean loop = false;
 do {
 try {
 
 loop = !executor.awaitTermination(2, TimeUnit.SECONDS);
 } catch (InterruptedException ignored) {
 }
 } while (loop);
 }
 }
 
 | 
使用方法
新建一个单元测试类 贴上下列代码 用于打印 2016 年至今的所有日期
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 
 | @Testpublic void threadTest(){
 Calendar start = Calendar.getInstance();
 start.set(2016, Calendar.JANUARY, 1, 0, 0, 0);
 Calendar end = Calendar.getInstance();
 
 ExecutorKit.execute(() -> {
 while (start.getTime().getTime() <= end.getTime().getTime()) {
 System.out.println(start.getTime());
 start.add(Calendar.DAY_OF_YEAR, 1);
 }
 });
 
 ExecutorKit.shutdownAndWait();
 }
 
 | 
经过测试 可以完整的打印所有的内容