如何在junit中使用未捕获的exception处理程序进行multithreading测试?

我有以下代码,我希望成功运行完成,但代码在“失败”(“不应该达到”)行失败;“。 有人可以解释为什么不调用默认的未捕获exception处理程序:

public class UncaughtExceptionTest extends TestCase implements UncaughtExceptionHandler { private final List uncaughtExceptions = new CopyOnWriteArrayList(); class UncaughtExceptionTestInnerClass implements Runnable { private final ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(1); private final CountDownLatch latch; UncaughtExceptionTestInnerClass(CountDownLatch latch) { this.latch = latch; executor.schedule(this, 50, TimeUnit.MILLISECONDS); } @Override public void run() { System.out.println("This is printed"); fail("this should fail"); latch.countDown(); } } @Test public void testUncaughtExceptions() { Thread.setDefaultUncaughtExceptionHandler(this); CountDownLatch latch = new CountDownLatch(1); UncaughtExceptionTestInnerClass testTheInnerClass = new UncaughtExceptionTestInnerClass(latch); try { if (!latch.await(1, TimeUnit.SECONDS)) { if (uncaughtExceptions.size() > 0) { Throwable exception = uncaughtExceptions.get(0); System.out.println("First uncaught exception: " + exception.getMessage()); } else { fail("this should not be reached"); } } } catch (InterruptedException e) { e.printStackTrace(); } } @Override public void uncaughtException(Thread t, Throwable e) { uncaughtExceptions.add(e); } } 

它与您使用Executor运行任务的事实有关。 仅当线程即将因未捕获的exception而终止时,才会调用未捕获的exception处理程序。 如果您将实现更改为使用普通线程,以便线程将以exception终止,您将看到预期的行为。

根据您提交任务的方式,执行程序线程可能会捕获所有Throwable并处理它们。 因此,线程不会因为这些exception而终止,因此未捕获的exception处理程序不会涉及。 例如, ThreadPoolExecutor.execute(Runnable)将触发未捕获的exception处理程序。 但是, ThreadPoolExecutor.submit(Callable)不会。 此外, ScheduledThreadPoolExecutor.schedule()也没有(它与他们使用FutureTask进行实现有关)。

使用执行程序服务访问意外exception的更好方法是通过Future

ScheduledThreadPoolExecutor.schedule()采用Runnable / Callable参数,而不是Thread 。 前者没有运行时exception处理程序。 在runcall方法中为RuntimeException设置try / catch块。