如何在junit中使用未捕获的异常处理程序进行多线程测试? [英] How to use an uncaught exception handler for a multi-thread test in junit?

查看:139
本文介绍了如何在junit中使用未捕获的异常处理程序进行多线程测试?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下代码,希望可以成功运行以完成代码,但是代码在"fail(这不应该到达");行失败.有人可以解释为什么未调用默认未捕获异常处理程序的原因吗?

I have the following code that I expect to run successfully to completion but the code fails at the line "fail("this should not be reached");". Can someone please explain why the default uncaught exception handler is not called:

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);
    }
}

推荐答案

这与您使用 Executor 运行任务这一事实有关.仅当线程由于未捕获的异常而将要终止时,才会调用未捕获的异常处理程序.如果将实现更改为使用普通线程,以便该线程将终止并带有异常,则将看到预期的行为.

It has to do with the fact you're using an Executor to run the task. The uncaught exception handler is invoked only if the thread is about to be terminated due to an uncaught exception. If you change your implementation to use a plain thread so that the thread will terminate with the exception, you will see the expected behavior.

根据您提交任务的方式,执行程序线程可能会捕获所有Throwables并对其进行处理.因此,线程不会由于这些异常而终止,因此未捕获的异常处理程序也不会参与.例如, ThreadPoolExecutor.execute(Runnable)将触发未捕获的异常处理程序.但是, ThreadPoolExecutor.submit(Callable)不能.另外, ScheduledThreadPoolExecutor.schedule()也不是(这与他们使用FutureTask来实现)有关.

Depending on how you submit tasks, the executor thread may catch all Throwables and handle them. Therefore, the thread does not terminate due to these exceptions, and thus the uncaught exception handler does not get involved. For example, ThreadPoolExecutor.execute(Runnable) will trigger the uncaught exception handler. However, ThreadPoolExecutor.submit(Callable) does not. Also, ScheduledThreadPoolExecutor.schedule() does not either (it has to do with their use of FutureTask for implementation).

通过执行程序服务访问意外异常的更好方法是通过未来.

A better way of accessing unexpected exceptions with an executor service is via Future.

这篇关于如何在junit中使用未捕获的异常处理程序进行多线程测试?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆