測試方法啟動子執行緒發送郵件,主執行緒結束後程序直接退出,子執行緒任務未完成、郵件未發出,無任何異常拋出。
public static void main(String[] args) {
TestResult r = new TestRunner().start(args);
if (!r.wasSuccessful()) System.exit(1);
System.exit(0); // 主執行緒結束即強制 JVM 退出
}
System.exit() 會終結整個 JVM,子執行緒來不及執行即被強制殺掉。
@Test public void testThread() {
new Thread(() -> {
for (int i=0; i<10000; i++)
System.out.println("i=" + i + " time=" + System.currentTimeMillis());
}).start();
// 無等待,主執行緒直接結束
}
輸出僅到 ~750 循環即中斷。
Thread.sleep(5000); // 盲目等待,時間難把控
@Test public void testThread() throws InterruptedException {
CountDownLatch latch = new CountDownLatch(1);
new Thread(() -> {
try {
for (int i=0; i<10000; i++) { /* work */ }
} finally {
latch.countDown(); // 任務完成釋放
}
}).start();
latch.await(5, TimeUnit.MINUTES); // 阻塞主執行緒,最多等 5 分鐘
}
countDown() → 主執行緒繼續。社區有現成 ConcurrentTestRunner,原理為重寫 run() 收集所有子執行緒 join(),有興趣可自行搜尋接入。
JUnit 4/5 預設不支援測試方法內啟動的守護執行緒存活超過主執行緒,務必使用 CountDownLatch、CompletableFuture 或 Thread.join() 顯式同步。