java线程池ThreadPool处理线程异常

原因:由于线程不阻碍主线程,所以线程发生异常,除非在日志里查看或者线程方法有try catch处理,否则很难发现异常,所以需要个兜底的方法,而线程中有个new Thread().setUncaughtExceptionHandler();
可以帮助我们处理这种未捕获异常,而在线程池中,则需要我们重写new ThreadFactory,从线程工厂中,即 executor.setThreadFactory();这里可以将线程异常做兜底处理(发送邮件通知或者try catch)

以下代码

线程池

/**
 * author chenkang
 */
@Configuration
@EnableAsync
@Log4j2
//注解线程池  使用时注意Async失效的情况
public class ThreadPoolConfig {
    @Resource
    private MyThreadFactory myThreadFactory;
    //获取当前cpu 核数
    public static final int cpuNum = Runtime.getRuntime().availableProcessors();
 
    //一般线程池
    @Bean("taskExecutor")
    public Executor getAsyncExecutor(){
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        //线程池核心线程数
        executor.setCorePoolSize(cpuNum);
        //线程池最大线程数
        executor.setMaxPoolSize(cpuNum * 2);
        //线程池队列大小
        executor.setQueueCapacity(Runtime.getRuntime().availableProcessors()*10);
        //线程活跃时间
        executor.setKeepAliveSeconds(30000);
        executor.setThreadFactory(myThreadFactory);
        //线程名称前缀
        executor.setThreadNamePrefix("sungrow-executor-");
        //线程池拒绝策略
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        executor.initialize();
        return executor;
    }
}

threadFactory

package org.jeecg.common.config;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.extra.mail.MailAccount;
import cn.hutool.extra.mail.MailUtil;
import lombok.Data;
import org.jeecg.common.util.RedisProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Component;


import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.concurrent.ThreadFactory;
//自定义threadFactory
@Component
@Data
public class MyThreadFactory implements ThreadFactory {
    @Autowired
    private ThreadErrorModel threadErrorModel;
    @Override
    public Thread newThread(Runnable r) {
        Thread thread = new Thread(r);
        thread.setUncaughtExceptionHandler((t, e) -> {
            String result = generateErrorMessage(e);
            sendEmailMessage(result);
        });
        return thread;
    }

    /**
     * 发送报错信息到开发邮箱
     * @param result
     */
    private void sendEmailMessage(String result) {
        MailAccount account = new MailAccount();
        account.setHost(threadErrorModel.getHost());
        account.setPort(threadErrorModel.getPort());
        account.setAuth(true);
        account.setFrom(threadErrorModel.getFrom());
        account.setUser(threadErrorModel.getUser());
        account.setPass(threadErrorModel.getPass());
        MailUtil.send(account,threadErrorModel.getEmails(), "慧碳平台线程错误,请开发协助调查", result, false);
    }

    /**
     * 生产报错信息
     * @param e
     * @return result
     */
    private String generateErrorMessage(Throwable e) {
        StackTraceElement[] stackTraceElements = e.getStackTrace();
        String result = e + "\n";
        for (int index = stackTraceElements.length - 1; index >= 0; --index) {
            result += "at [" + stackTraceElements[index].getClassName() + ",";
            result += stackTraceElements[index].getFileName() + ",";
            result += stackTraceElements[index].getMethodName() + ",";
            result += stackTraceElements[index].getLineNumber() + "]\n";
        }
        return result;
    }
}

配置发送邮件信息

package org.jeecg.common.config;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;

import java.util.ArrayList;
import java.util.List;

@Data
@Configuration
@ConfigurationProperties(prefix = "thread.error.email")
public class ThreadErrorModel {
    private String host;
    private int port;
    private String auth;
    private String from;
    private String user;
    private String pass;
    private List<String> emails;
}

yaml 配置文件

在这里插入图片描述

测试:

package org.jeecg.modules.system.controller;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.extra.mail.MailAccount;
import cn.hutool.extra.mail.MailUtil;
import lombok.extern.log4j.Log4j2;
import org.jeecg.common.exception.JeecgBootException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.io.File;
import java.io.FileNotFoundException;

//线程池测试
@RestController
@RequestMapping("/test")
@Log4j2
public class TestThreadPoolController {
    @Resource
    private ThreadPoolTaskExecutor taskExecutor;
    @GetMapping("/threadPool")
    public void testThreadPool(){
        taskExecutor.execute(()->{
                log.info("=============="+Thread.currentThread().getName());
                  int a = 3/0;
        });
        log.info("kang异常");
    }
}

产生异常但并不阻碍主线程,如果不是一直盯着日志并且没有try catch异常,则很难发现异常

在这里插入图片描述
查看邮件 收到异常邮件,开发运维可以排除异常

在这里插入图片描述

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值