写过单元测试的同学应该遇到过这个问题 单元测试中新建的线程 一般都不会被运行 这是因为JUnit在底层实现上是用 System.exit()
退出的
问题原因
查看JUnit4的TestRunner的源码
1 2 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()
可以检测所有线程是否执行完毕 可以通过循环判断来达到防止主线程退出的目的
下面提供一个工具类
1 2 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 年至今的所有日期
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| @Test public 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(); }
|
经过测试 可以完整的打印所有的内容