Java 如何在junit中为多线程测试使用未捕获的异常处理程序?

Java 如何在junit中为多线程测试使用未捕获的异常处理程序?,java,multithreading,junit,Java,Multithreading,Junit,我有下面的代码,我希望能够成功运行到完成,但是代码在“fail”(“this should not reach”);”行失败。有人能解释一下为什么不调用默认的未捕获异常处理程序吗: public class UncaughtExceptionTest extends TestCase implements UncaughtExceptionHandler { private final List<Throwable> uncaughtExceptions =

我有下面的代码,我希望能够成功运行到完成,但是代码在“fail”(“this should not reach”);”行失败。有人能解释一下为什么不调用默认的未捕获异常处理程序吗:

public class UncaughtExceptionTest extends TestCase
    implements UncaughtExceptionHandler {

    private final List<Throwable> uncaughtExceptions =
        new CopyOnWriteArrayList<Throwable>();

    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);
    }
}
公共类UncaughtExceptionTest扩展了TestCase
实现UncaughtExceptionHandler{
私有最终列表未捕获异常=
新建CopyOnWriteArrayList();
类UncaughtExceptionTestInerClass实现Runnable{
私有最终调度线程池执行器执行器=
新的ScheduledThreadPoolExecutor(1);
私有最终倒计时闩锁;
UncaughtExceptionTestInReclass(倒计时闩锁闩锁){
this.latch=闩锁;
执行者计划(这个,50,时间单位为毫秒);
}
@凌驾
公开募捐{
System.out.println(“已打印”);
失败(“本应失败”);
倒计时();
}
}
@试验
public void testUncaughtExceptions(){
setDefaultUncaughtExceptionHandler(this);
CountDownLatch闩锁=新的CountDownLatch(1);
UncaughtExceptionTestInReclass测试InReclass=
新的UncaughtExceptionTestInnerClass(闩锁);
试一试{
如果(!闩锁等待(1,时间单位秒)){
如果(uncaughtExceptions.size()>0){
Throwable exception=uncaughtExceptions.get(0);
System.out.println(“第一个未捕获的异常:”+
异常。getMessage());
}
否则{
失败(“不应达到此目标”);
}
}
}捕捉(中断异常e){
e、 printStackTrace();
}
}
@凌驾
公共无效未捕获异常(线程t,可丢弃的e){
添加(e);
}
}

这与您正在使用执行器运行任务有关。只有当线程由于未捕获异常即将终止时,才会调用未捕获异常处理程序。如果您将实现更改为使用普通线程,以便线程将以异常终止,您将看到预期的行为

根据您提交任务的方式,executor线程可能会捕获并处理所有丢弃的任务。因此,线程不会因为这些异常而终止,因此未捕获的异常处理程序不会参与其中。例如,ThreadPoolExecutor.execute(Runnable)将触发未捕获异常处理程序。但是,ThreadPoolExecutor.submit(可调用)不会。另外,ScheduledThreadPoolExecutor.schedule()也没有(这与它们使用FutureTask实现有关)


使用executor服务访问意外异常的更好方法是通过Future

ScheduledThreadPoolExecutor。schedule()
采用
可运行的
/
可调用的
参数,而不是
线程
。前者没有运行时异常处理程序。在
run
call
方法中为
RuntimeException
设置一个
try
/
catch
块。

为什么
失败(“这应该失败”)行吗?这是故意的吗?这样门闩就不会倒计时了。@BalusC:是的,这是故意的。为了正确地通过测试,lock.await()方法应该超时,从而使其返回false。然后,代码应该打印来自在您询问的行上抛出的未捕获断言FailedError异常的消息。