如何优雅解决线程池中的异常?-创新互联

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

让客户满意是我们工作的目标,不断超越客户的期望值来自于我们对这个行业的热爱。我们立志把好的技术通过有效、简单的方式提供给客户,将通过不懈努力成为客户在信息化领域值得信任、有价值的长期合作伙伴,公司提供的服务项目有:域名申请网站空间、营销软件、网站建设、南涧网站维护、网站推广。
@Test
public void test() throws Exception {
    ThreadPoolExecutor threadPoolExecutor = 
            new ThreadPoolExecutor(5, 10, 60,
            TimeUnit.SECONDS, 
            new ArrayBlockingQueue<>(100000));
    Futuresubmit = threadPoolExecutor.execute(() ->{
        try {
            int i = 1 / 0;
            return i;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return null;
        }
    });
}

但是当线程池调用方法很多时,那么每个线程执行方法内都要 try/catch处理,这就不优雅了,其实ThreadPoolExecutor类还支持传入 ThreadFactory参数,自定义线程工厂,在创建 thread时,指定 setUncaughtExceptionHandler异常处理方法,这样就可以做到全局处理异常了,代码如下:

ThreadFactory threadFactory = r ->{
    Thread thread = new Thread(r);
    thread.setUncaughtExceptionHandler((t, e) ->{
        // 记录线程异常
        log.error(e.getMessage(), e);
    });
    return thread;
};
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5, 10, 60,
        TimeUnit.SECONDS, new ArrayBlockingQueue<>(100000),
        threadFactory);
threadPoolExecutor.execute(() ->{
    log.info("---------------------");
    int i = 1 / 0;
});

线程池决绝策略设置错误导致业务接口执行超时

先介绍下线程池得四种决绝策略

  • AbortPolicy:丢弃任务并抛出RejectedExecutionException异常,这是线程池默认的拒绝策略
  • DiscardPolicy:丢弃任务,但是不抛出异常。如果线程队列已满,则后续提交的任务都会被丢弃,且是静默丢弃。 使用此策略,可能会使我们无法发现系统的异常状态。建议是一些无关紧要的业务采用此策略
  • DiscardOldestPolicy:丢弃队列最前面的任务,然后重新提交被拒绝的任务。此拒绝策略,是一种喜新厌旧的拒绝策略。是否要采用此种拒绝策略,还得根据实际业务是否允许丢弃老任务来认真衡量。
  • CallerRunsPolicy:由调用线程处理该任务

如下是一个线上业务接口使用得线程池配置,决绝策略采用 CallerRunsPolicy

// 某个线上线程池配置如下
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
                50, // 最小核心线程数
                50, // 大线程数,当队列满时,能创建的大线程数
                60L, TimeUnit.SECONDS, // 空闲线程超过核心线程时,回收该线程的大等待时间
                new LinkedBlockingQueue<>(5000), // 阻塞队列大小,当核心线程使用满时,新的线程会放进队列
            new CustomizableThreadFactory("task"), // 自定义线程名
                new ThreadPoolExecutor.CallerRunsPolicy() // 线程执行的拒绝策略
        );

在某些情况下,子线程任务调用第三方接口超时,导致核心线程数、大线程数占满、阻塞队列占满的情况下执行拒绝策略时,由于使用 CallerRunsPolicy策略,导致业务线程执行子任务时继续超时,进而导致接口执行异常,这种情况下,考虑到子线程任务得重要性,不是很重要得话,可以使用 DiscardPolicy策略,要是很重要,可以发送到消息队列中持久化子线程任务数据待后续处理

你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧


网页题目:如何优雅解决线程池中的异常?-创新互联
文章链接:http://ybzwz.com/article/ddedpd.html