【问题标题】:UncaughtExceptionHandler behaves unexpectedly, then freezesUncaughtExceptionHandler 行为异常,然后冻结
【发布时间】:2013-09-27 20:41:23
【问题描述】:

我的消费者没有按照我期望的方式工作。下面是sscce 在我的真实程序中发生的事情。

  • 预期:
    1. 打印In finally!
    2. 打印About to print stacktrace
    3. 打印NullPointerException 堆栈跟踪。
  • 实际:
    1. 打印In finally!
    2. 挂在sun.misc.Unsafe

程序:

import java.lang.Thread.UncaughtExceptionHandler;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;

public class ThreadTest implements Runnable {
    public static void main(String... args) {
        ExecutorService service = Executors.newSingleThreadExecutor(new ThreadFactory() {
                    @Override
                    public Thread newThread(Runnable r) {
                        Thread newThread = new Thread(r);
                        newThread.setUncaughtExceptionHandler(new MyExceptionHandler());
                        return newThread;
                    }
                });
        service.submit(new ThreadTest());
    }

    private static class MyExceptionHandler implements UncaughtExceptionHandler {
        @Override
        public void uncaughtException(Thread t, Throwable e) {
            System.out.println("About to print stacktrace");
            e.printStackTrace();
        }
    }

    @Override
    public void run() {
        Object foo = null;
        try {
            while(!Thread.interrupted()) {
                Thread.sleep(1000);
                System.out.println(foo.toString());
                System.out.println("After npe!");
            }
        } catch(InterruptedException e) {

        } finally {
            System.out.println("In finally!");
        }
    }
}

【问题讨论】:

    标签: java multithreading executorservice uncaughtexceptionhandler


    【解决方案1】:

    在 Executor 中运行的 Runnables 不会真正抛出异常,这会影响线程的未捕获异常处理程序。相反,Runnable 用捕获 Throwable 的代码包装。这样一来,Future 可以返回从任务中抛出的异常。

    正如@Gray 在下面的 cmets 中指出的那样,您的程序正在“挂起”,因为线程池线程正在阻止程序退出。您的可运行对象已完成,线程池线程正在等待新任务。如果您关闭线程池,您的程序将正常完成(或使线程池线程守护进程)。

    【讨论】:

    • 为什么会挂起?
    • 它挂起是因为你没有关闭你的执行器服务@durron597。
    • 你可能应该使用Callable,一旦你调用future.get()就会抛出NPE。
    • @Gray - OP 不需要使用 Callable 来使其工作,只需等待返回的 Future。
    • 真@jtahlborn。如果我想要投球,我会本能地转向Callable,因为它会强制接球,但当它是RuntimeException时你是对的。
    猜你喜欢
    • 1970-01-01
    • 2012-02-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多