当前位置: 首页 > 面试题库 >

为什么ExecutorService不调用UncaughtExceptionHandler?

公孙宸
2023-03-14
问题内容

我偶然发现了一个问题,可以总结如下:

当我手动创建线程(即通过实例化java.lang.Thread)时,UncaughtExceptionHandler将适当地调用它。但是,当我ExecutorService与一起使用时ThreadFactory,处理程序将被忽略。我错过了什么?

public class ThreadStudy {

private static final int THREAD_POOL_SIZE = 1;

public static void main(String[] args) {

    // create uncaught exception handler

    final UncaughtExceptionHandler exceptionHandler = new UncaughtExceptionHandler() {

        @Override
        public void uncaughtException(Thread t, Throwable e) {
            synchronized (this) {
                System.err.println("Uncaught exception in thread '" + t.getName() + "': " + e.getMessage());
            }
        }
    };

    // create thread factory

    ThreadFactory threadFactory = new ThreadFactory() {

        @Override
        public Thread newThread(Runnable r) {
            // System.out.println("creating pooled thread");
            final Thread thread = new Thread(r);
            thread.setUncaughtExceptionHandler(exceptionHandler);
            return thread;
        }
    };

    // create Threadpool

    ExecutorService threadPool = Executors.newFixedThreadPool(THREAD_POOL_SIZE, threadFactory);

    // create Runnable

    Runnable runnable = new Runnable() {

        @Override
        public void run() {
            // System.out.println("A runnable runs...");
            throw new RuntimeException("Error in Runnable");
        }
    };

    // create Callable

    Callable<Integer> callable = new Callable<Integer>() {

        @Override
        public Integer call() throws Exception {
            // System.out.println("A callable runs...");
            throw new Exception("Error in Callable");
        }
    };

    // a) submitting Runnable to threadpool
    threadPool.submit(runnable);

    // b) submit Callable to threadpool
    threadPool.submit(callable);

    // c) create a thread for runnable manually
    final Thread thread_r = new Thread(runnable, "manually-created-thread");
    thread_r.setUncaughtExceptionHandler(exceptionHandler);
    thread_r.start();

    threadPool.shutdown();
    System.out.println("Done.");
}
}

我期望:消息“未捕获的异常…”的三倍

我得到:消息一次(由手动创建的线程触发)。

在Windows 7和Mac OS X 10.5上用Java 1.6复制。


问题答案:

因为异常不会被捕获。

您的ThreadFactory生成的线程没有直接赋予您的Runnable或Callable。相反,您获得的Runnable是内部Worker类,例如,请参阅ThreadPoolExecutor
$ Worker。尝试System.out.println()在示例中为newThread提供Runnable。

该Worker捕获您提交的作业中的所有RuntimeException。

您可以在ThreadPoolExecutor#afterExecute方法中获取异常。



 类似资料:
  • 问题内容: 我通过扩展和实现和创建了自己的Android帐户身份验证器。其中的某些方法由调用,而其他方法则没有。 这很好用: 当我打电话给我时,问题就发生了。AccountManager不会调用我在中定义的方法。它调用其他一些默认方法,该方法仅在启动之前检查是否存在。 这是行不通的。它没有调用我的方法: AuthenticatorService 我创建了服务并定义了。否则不应该工作。 编辑: 我在

  • 问题内容: 未能调用线程执行器将导致应用程序永不终止。 关闭ExecutorService的最佳实践是: 既然Java知道try-with-resources概念,那么如果我们能做到这一点岂不是很好吗? 问题答案: 该ExecutorService实际上具有 两种 与关机有关的方法;基于一个简单的事实,即关闭服务的 两种 方式都有意义。 因此:您将如何自动关闭服务?以一致的方式为每个人工作?! 因

  • 问题内容: 我只是很好奇,是否有人知道django的orm是否有充分的理由不对模型调用’full_clean’,除非将其保存为模型表单的一部分。 请注意,当你调用模型的save()方法时,不会自动调用full_clean()。要为自己创建的模型运行单步模型验证时,需要手动调用它。 django的完整档案 (注意:报价已针对Django 1.6更新…之前的django文档也对ModelForms提出

  • 问题内容: 我正在尝试制作我的第一个Android应用程序。我注意到,如果数据库不存在,则不会调用该方法来创建表。但是,即使我尝试调试,该方法也无法正常工作。 请查看下面的代码,并给我任何建议。任何帮助将不胜感激。 问题答案: 我也遇到了 SQLiteOpenHelper的 麻烦。对我有用的是存储成员变量 在SQLiteOpenHelper子类中并调用 在构造函数中。 该问题的答案还包括一些有用的

  • 问题内容: 除了JSONP,为什么要遵循相同的域策略? 问题答案: 出于安全原因,已实施“同源起源策略”;引用维基百科的相关句子: 这种机制对现代Web应用程序具有特殊的意义,因为Web服务器广泛依赖于HTTP cookie来维护经过身份验证的用户会话,因为服务器基于HTTP cookie信息进行操作以揭示敏感信息或执行状态更改操作。 必须在客户端维护不相关站点提供的内容之间的严格分隔,以防止丢失

  • 我正在使用forEach循环一个nodeList。我的代码如下 此代码引发错误为 未捕获的TypeError:Array.Foreach不是函数 然而,一些较旧的浏览器还没有实现nodelist.foreach()和array.from()。但是这些限制可以通过使用array.prototype.foreach()来规避(本文档中有更多内容)。 参考:MDN