处理非正常的线程终止

424 阅读2分钟

在我们的应用程序中会应用到大量的多线程,然而在处理多线程程序时,如何获取线程的非正常终止(一般是遇到RuntimeException)是一件令人头疼的问题,因为线程池中的一个线程出现异常终止是很难发现的。本文给出两种方式用于感知多线程中的非正常终止

UncaughtExceptionHandler

在Thread类中存在一个UncaughtExceptionHandler接口用于处理未捕获的异常,当我们未设置该项时,其默认会将错误信息输出到System.err,通过实现该接口,我们可以自定义异常处理,用于记录或者恢复线程。要为线程池中的每一个线程设置UncaughtExceptionHandler,需要为ThreadPoolExecutor设置一个ThreadFactory,由ThreadFactory设置UncaughtExceptionHandler

示例:

static class LogUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler {
    @Override
    public void uncaughtException(Thread t, Throwable e) {
        System.out.println(t.getName() + " ===> " + e);
    }
}

public static void main(String[] args) {
    ThreadFactory threadFactory = new ThreadFactoryBuilder().setUncaughtExceptionHandler(new LogUncaughtExceptionHandler()).build();
    ExecutorService singleThread = new ThreadPoolExecutor(1, 1, 1L, TimeUnit.SECONDS, new ArrayBlockingQueue<>(10), threadFactory);
    singleThread.execute(() -> {
        System.out.println("ready to throws a exception");
        throw new RuntimeException("Test!!!");
    });
}

Output:
ready to throws a exception
pool-1-thread-1 ===> java.lang.RuntimeException: Test!!!

afterExecute

ThreadPoolExecutor中有一个afterExecutor方法,该方法有两个参数,Runnable和Throwable,当发生异常时,可以通过Throwable参数获取错误原因,通过重写该方法我们可以自定义线程非正常退出时的策略 示例:

static class MyThreadPoolExecutor extends ThreadPoolExecutor {
    MyThreadPoolExecutor() {
        super(1, 1, 1L, TimeUnit.SECONDS, new ArrayBlockingQueue<>(10), new ThreadPoolFactoryBuilder().build());
    }
    
    @Override
    protected void afterExecute(Runnable r, Throwable t) {
        System.out.println(t == null);
    }
}

public static void main(String[] args) {
    ExecutorService threadPool = new MyThreadPoolExecutor();
    threadPool.execute(() -> {
        System.out.println("ready to throws a exception");
        throw new RuntimeException("Test!!!");
    });
}

Output:
ready to throws a exception
false

注:有一点需要注意的是,只有通过ExecutorService.execute方法才可以实现,而使用submit方法的话,无论是受检查异常还说运行时异常,都将被认为是任务返回状态的一部分