• springboot 使用多线程和线程池


    日常业务中,出于及时响应和效率问题对于涉及日志类的保存操作经常使用多线程处理,这里展示其中的一种调用方式。
    因为博主本人不喜欢@Async注解对启动类的侵入,所以使用Runnable接口配合线程池实现多线程的使用。

    • 步骤一:创建自定义线程池配置类

    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
    
    /**
     * 线程池配置类
     *
     * @author gbx
     */
    @Configuration
    public class ThreadPoolConfig {
    
        /**
         * 公共线程池
         */
        @Bean
        public ThreadPoolTaskExecutor commonThreadPoolTaskExecutor() {
            ThreadPoolTaskExecutor pool = new org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor();
            // 返回可用处理器的Java虚拟机的数量
            int processNum = Runtime.getRuntime().availableProcessors();
            int corePoolSize = (int) (processNum / (1 - 0.2));
            int maxPoolSize = (int) (processNum / (1 - 0.5));
            // 核心池大小
            pool.setCorePoolSize(corePoolSize);
            // 最大线程数
            pool.setMaxPoolSize(maxPoolSize);
            // 队列程度
            pool.setQueueCapacity(maxPoolSize * 1000);
            pool.setThreadPriority(Thread.MAX_PRIORITY);
            pool.setDaemon(false);
            // 线程空闲时间
            pool.setKeepAliveSeconds(300);
            return pool;
        }
    }
    
    
    • 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
    • 步骤二:创建Runnable接口的实现类(通过构造方法传入所需参数和对象,在run方法实现相关操作逻辑)

    /**
     * 多线程任务
     *
     * @author gbx
     */
    public interface ITaskService extends Runnable {
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    import com.gbx.sms.platform.common.exception.ErrorException;
    import com.gbx.sms.platform.module.yidong.domain.SmsLogs;
    import com.gbx.sms.platform.module.yidong.dto.YiDongDTO;
    import com.gbx.sms.platform.module.yidong.service.ISmsLogsService;
    import com.gbx.sms.platform.module.yidong.service.ITaskService;
    import lombok.extern.slf4j.Slf4j;
    import org.apache.commons.lang3.StringUtils;
    
    /**
     * 多线程任务 功能实现
     *
     * @author gbx
     */
    @Slf4j
    public class TaskServiceImpl implements ITaskService {
    
        private ISmsLogsService logsService;
        private YiDongDTO yiDongDTO;
    
        public TaskServiceImpl(ISmsLogsService logsService, YiDongDTO yiDongDTO) {
            this.logsService = logsService;
            this.yiDongDTO = yiDongDTO;
        }
    
        @Override
        public void run() {
            SmsLogs smsLogs = SmsLogs.builder()
                    .appKey(yiDongDTO.getAppKey())
                    .appName(yiDongDTO.getAppName())
                    .modeCode(yiDongDTO.getModeCode())
                    .modeName(yiDongDTO.getModeName())
                    .reqMsg(yiDongDTO.getReqMsg())
                    .phone(yiDongDTO.getPhone())
                    .build();
            String content = yiDongDTO.getContent();
            if (StringUtils.isNotBlank(content)) {
                if (content.length() > 200) {
                    content = content.substring(0, 200);
                }
                smsLogs.setSmsContent(content);
            }
            String code = yiDongDTO.getCode();
            if (StringUtils.isNotBlank(code)) {
                smsLogs.setSmsCode(code);
            }
            int add = logsService.insertSmsLogs(smsLogs);
            if (add <= 0) {
                throw new ErrorException("添加短信调用日志失败,参数:" + yiDongDTO.toString());
            }
        }
    }
    
    
    • 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
    • 步骤三:对实现多线程的方法进行调用

    import cn.hutool.core.lang.Validator;
    import cn.hutool.core.util.ObjectUtil;
    import com.alibaba.fastjson.JSON;
    import com.alibaba.fastjson.JSONObject;
    import com.gbx.sms.platform.common.constant.HttpStatus;
    import com.gbx.sms.platform.common.core.bean.Result;
    import com.gbx.sms.platform.common.exception.ErrorException;
    import com.gbx.sms.platform.common.utils.SmsSendUtil;
    import com.gbx.sms.platform.module.yidong.domain.SmsAuth;
    import com.gbx.sms.platform.module.yidong.domain.SmsLogs;
    import com.gbx.sms.platform.module.yidong.domain.SmsMode;
    import com.gbx.sms.platform.module.yidong.dto.YiDongDTO;
    import com.gbx.sms.platform.module.yidong.service.*;
    import lombok.extern.slf4j.Slf4j;
    import org.apache.commons.codec.digest.DigestUtils;
    import org.apache.commons.lang3.StringUtils;
    import org.apache.tomcat.util.codec.binary.Base64;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.data.redis.core.RedisTemplate;
    import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
    import org.springframework.stereotype.Service;
    
    import javax.annotation.Resource;
    import java.time.LocalDateTime;
    import java.time.temporal.ChronoUnit;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    import java.util.concurrent.TimeUnit;
    
    /**
     * 移动平台发送短信功能实现
     *
     * @author gbx
     */
    @Service
    @Slf4j
    public class SmsYiDongServiceImpl implements SmsYiDongService {
        @Autowired
        private ISmsLogsService logsService;
        @Autowired
        private ThreadPoolTaskExecutor commonThreadPoolTaskExecutor;
    
        /**
         * 仅发送短信提醒结果告知类消息(非验证码类的结果通知类,提醒类消息)
         *
         * @param yiDongDTO 包含短信发送相关参数信息的实体
         * @return 处理结果
         */
        @Override
        public Result onlySendSmsMsg(YiDongDTO yiDongDTO) {
                    //此处使用线程池的额外线程执行
                    try {
                        ITaskService taskService = new TaskServiceImpl(logsService, yiDongDTO);
                        commonThreadPoolTaskExecutor.execute(taskService);
                    } catch (Exception eA) {
                        log.error(eA.getMessage());
                    }
        }
    }
    
    • 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

    至此,成功实现多线程的使用,可以使用Thread.sleep()查看是否成功。

  • 相关阅读:
    Open-TeleVision——通过VR沉浸式感受人形机器人视野:兼备远程控制和深度感知能力
    Spring拦截器的简单应用
    Go by Example for循环
    Python全攻略:基础学习、爬虫编程实战和面试技巧
    企望制造ERP存在远程命令执行漏洞 附POC
    漏洞扫描工具的编写
    普遍前端开发的接口交互和前端调用智能合约
    顺序表实现集合并集
    node实战——koa实现文件下载和图片/pdf/视频预览(node后端储备知识)
    echarts、dataV 数据可视化大屏
  • 原文地址:https://blog.csdn.net/yssa1125001/article/details/125503414