利用 ThreadFactory 统一处理异常

线程池的使用必不可少,使用无返回值 execute() 方法时,线程执行发生异常的话,需要记录日志,方便回溯,一般做法是在线程执行方法内 try/catch 处理 ,如下所示:

@Test
public void thread() {
    ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5, 10, 60, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(100));
    threadPoolExecutor.execute(() -> {
        try {
            log.info(Thread.currentThread().getName());
            int i = (1 / 0);
        } catch (Exception e) {
            log.error("发生异常 => {}", e);
        }
    });

    try {
        Thread.sleep(10000000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

因为线程池一般情况下,都不会在一个项目里创建多个线程池,那么随着线程池在项目中多个地方提交任务时,使用 try/catch 进行异常捕获和记录,对于整个线程池管理非常不方便。我们可以通过利用 ThreadFactory ,在创建线程时,指定 setUncaughtExceptionHandler 异常处理方法,这样就可以做到全局处理异常。

@Test
public void test() {
    ThreadFactory threadFactory = r -> {
        Thread thread = new Thread(r);
        thread.setName("testThread");
        thread.setUncaughtExceptionHandler((t, err) -> {
            log.info(t.getName());
            log.error("err => {}", err);
        });
        return thread;
    };
    ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5, 10, 60, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(100), threadFactory);
    //        threadPoolExecutor.setThreadFactory(threadFactory);
    threadPoolExecutor.execute(() -> {
        log.info(Thread.currentThread().getName());
        int i = (1 / 0);
    });

    try {
        Thread.sleep(10000000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}