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

发布于 2024-09-07 21:44:39 字数 1833 浏览 2 评论 0原文

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

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

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

墨离汐 2024-09-14 21:44:39

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

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

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

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.

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.

心在旅行 2024-09-14 21:44:39

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

ScheduledThreadPoolExecutor.schedule() takes a Runnable/Callable argument, not Thread. The former don't have runtime exception handlers. Have a try/catch block for a RuntimeException in your run or call method.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文