• java线程池捕获线程异常


    原因:由于线程不阻碍主线程,所以线程发生异常,除非在日志里查看或者线程方法有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;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    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;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67

    配置发送邮件信息

    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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    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异常");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

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

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

    在这里插入图片描述

  • 相关阅读:
    哈里斯鹰算法优化BP神经网络(HHO-BP)回归预测研究(Matlab代码实现)
    主板与品牌电脑启动快捷键
    猿创征文 | Java知识【数组上篇】
    umi4中的配置问题,我想用umirc.ts中alias配置没起作用。是我的用法不对吗?
    C++机票购买系统
    Linux 5.20 可能将版本号升级为 Linux 6.0
    LeetCode84:柱形图中最大的矩形
    工业智能网关BL110应用之三十九:LAN口如何配置采集Modbus协议设备S475
    想要精准营销,从学习搭建一套对的标签体系开始丨DTVision分析洞察篇
    mulesoft MCIA 易错题汇总解析
  • 原文地址:https://blog.csdn.net/weixin_43866043/article/details/126886163