zoukankan      html  css  js  c++  java
  • SpringBoot之SpringBoot整合异步线程调用注解

    SpringBoot之SpringBoot整合异步线程调用注解

    理念:

      为了快速响应浏览器,开启多线程执行任务

       但是有一个缺点,会增加CPU资源的消耗,所以大的项目推荐使用MQ消息队列

    编写代码:

        @GetMapping("/addDB")
        public String addDB() {
            // 模拟数据交互
            log.info("<01>");
            sms();
            log.info("<04>");
            return "用户注册成功";
        }
    
        /**
         * 模拟发送短信
         *
         * @return
         */
        public String sms() {
            log.info("<02>");
            try {
                log.info("正在发送短信...");
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "短信发送完成";
        }

    这个接口最少需要4秒才能返回,如果发送短信时间更长,返回时间增加,这样用户的体验就非常不好

    启动项目测试

     他是单线程去执行的,看过Tomcat的应该也知道,tomcat会为每一次请求从他的线程池中单独拿一个线程去执行,所以它是单线程 的

    所以这里就可以使用Spring提供的异步注解

    异步注解的使用:

    在方法上添加@Async注解

     并且在启动类中开启异步注解

    启动测试:

     不对呀,这还是单线程呀

    异步注解失效问题解决:

    需要把sms方法单独提取成一个类

    package com.springboot.demo.async;
    
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.scheduling.annotation.Async;
    import org.springframework.stereotype.Component;
    
    /**
     * @author ZYGisComputer
     */
    @Slf4j
    @Component
    public class SmsService {
    
        /**
         * 模拟发送短信
         *
         * @return
         */
        @Async
        public String sms() {
            log.info("<02>");
            try {
                log.info("正在发送短信...");
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "短信发送完成";
        }
        
    }

    通过Autowirld的方式注入使用

     再次测试

     可以看到执行成功了,并且也是不同的线程,但是他这样都是每次都是new一个新的线程,这显然是不合理的,因为使用线程就应该考虑采用线程池

    异步注解整合线程池:

    创建config包,并在下面创建ThreadPoolConfig.java

    package com.springboot.demo.config;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.core.task.TaskExecutor;
    import org.springframework.scheduling.annotation.EnableAsync;
    import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
    
    import java.util.concurrent.ThreadPoolExecutor;
    
    @Configuration
    @EnableAsync
    public class ThreadPoolConfig {
    
        /**
         * 每秒需要多少个线程处理?
         * tasks/(1/taskcost)
         */
        private int corePoolSize = 3;
    
        /**
         * 线程池维护线程的最大数量
         * (max(tasks)- queueCapacity)/(1/taskcost)
         */
        private int maxPoolSize = 3;
    
        /**
         * 缓存队列
         * (coreSizePool/taskcost)*responsetime
         */
        private int queueCapacity = 10;
    
        /**
         * 允许的空闲时间
         * 默认为60
         */
        private int keepAlive = 100;
    
        @Bean
        public TaskExecutor taskExecutor() {
            ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
            // 设置核心线程数
            executor.setCorePoolSize(corePoolSize);
            // 设置最大线程数
            executor.setMaxPoolSize(maxPoolSize);
            // 设置队列容量
            executor.setQueueCapacity(queueCapacity);
            // 设置允许的空闲时间(秒)
            //executor.setKeepAliveSeconds(keepAlive);
            // 设置默认线程名称
            executor.setThreadNamePrefix("thread-");
            // 设置拒绝策略rejection-policy:当pool已经达到max size的时候,如何处理新任务
            // CALLER_RUNS:不在新线程中执行任务,而是有调用者所在的线程来执行
            executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
            // 等待所有任务结束后再关闭线程池
            executor.setWaitForTasksToCompleteOnShutdown(true);
            return executor;
        }
    
    }

    在@Async注解中配置线程池名称就可以

     启动项目测试:

    2021-01-26 18:18:53,820 [http-nio-8082-exec-1] INFO (HelloService.java:76)- <01>
    2021-01-26 18:18:53,823 [http-nio-8082-exec-1] INFO (HelloService.java:78)- <04>
    2021-01-26 18:18:53,823 [http-nio-8082-exec-1] INFO (LogAspect.java:50)- RESPONSE : 用户注册成功
    2021-01-26 18:18:53,829 [thread-1] INFO (SmsService.java:24)- <02>
    2021-01-26 18:18:53,831 [thread-1] INFO (SmsService.java:26)- 正在发送短信...
    <执行定时任务>:18:18:56
    <执行定时任务>:18:19:01
    2021-01-26 18:19:01,340 [http-nio-8082-exec-3] INFO (LogAspect.java:37)- URL : http://localhost:8082/addDB
    2021-01-26 18:19:01,341 [http-nio-8082-exec-3] INFO (LogAspect.java:38)- HTTP_METHOD : GET
    2021-01-26 18:19:01,341 [http-nio-8082-exec-3] INFO (LogAspect.java:39)- IP : 0:0:0:0:0:0:0:1
    2021-01-26 18:19:01,341 [http-nio-8082-exec-3] INFO (HelloService.java:76)- <01>
    2021-01-26 18:19:01,342 [http-nio-8082-exec-3] INFO (HelloService.java:78)- <04>
    2021-01-26 18:19:01,342 [thread-2] INFO (SmsService.java:24)- <02>
    2021-01-26 18:19:01,342 [thread-2] INFO (SmsService.java:26)- 正在发送短信...
    2021-01-26 18:19:01,342 [http-nio-8082-exec-3] INFO (LogAspect.java:50)- RESPONSE : 用户注册成功
    2021-01-26 18:19:01,922 [http-nio-8082-exec-4] INFO (LogAspect.java:37)- URL : http://localhost:8082/addDB
    2021-01-26 18:19:01,922 [http-nio-8082-exec-4] INFO (LogAspect.java:38)- HTTP_METHOD : GET
    2021-01-26 18:19:01,923 [http-nio-8082-exec-4] INFO (LogAspect.java:39)- IP : 0:0:0:0:0:0:0:1
    2021-01-26 18:19:01,923 [http-nio-8082-exec-4] INFO (HelloService.java:76)- <01>
    2021-01-26 18:19:01,923 [http-nio-8082-exec-4] INFO (HelloService.java:78)- <04>
    2021-01-26 18:19:01,924 [thread-3] INFO (SmsService.java:24)- <02>
    2021-01-26 18:19:01,924 [http-nio-8082-exec-4] INFO (LogAspect.java:50)- RESPONSE : 用户注册成功
    2021-01-26 18:19:01,924 [thread-3] INFO (SmsService.java:26)- 正在发送短信...
    2021-01-26 18:19:02,559 [http-nio-8082-exec-2] INFO (LogAspect.java:37)- URL : http://localhost:8082/addDB
    2021-01-26 18:19:02,559 [http-nio-8082-exec-2] INFO (LogAspect.java:38)- HTTP_METHOD : GET
    2021-01-26 18:19:02,559 [http-nio-8082-exec-2] INFO (LogAspect.java:39)- IP : 0:0:0:0:0:0:0:1
    2021-01-26 18:19:02,559 [http-nio-8082-exec-2] INFO (HelloService.java:76)- <01>
    2021-01-26 18:19:02,560 [thread-1] INFO (SmsService.java:24)- <02>
    2021-01-26 18:19:02,560 [http-nio-8082-exec-2] INFO (HelloService.java:78)- <04>
    2021-01-26 18:19:02,560 [thread-1] INFO (SmsService.java:26)- 正在发送短信...
    2021-01-26 18:19:02,560 [http-nio-8082-exec-2] INFO (LogAspect.java:50)- RESPONSE : 用户注册成功

    可以看到使用完成thread-3之后使用的又是thread-1了,线程池的参数可以根据自己项目的实际情况调整,不懂线程池的可以去看看我写的《线程池理念分析及其手写

    到此整合异步注解完成

    作者:彼岸舞

    时间:2021126

    内容关于:SpringBoot

    本文来源于网络,只做技术分享,一概不负任何责任

  • 相关阅读:
    作业2 求题目中的数
    2013 C#单元测试
    实现项目WC
    带括号多项式版四则运算
    20道简单加减法随机生成程序扩展版体会
    20道简单加减法随机生成程序
    Jeesite 集成微信支付接口
    第一节:JAVA 语言的学习目标
    vector(未完)
    关于phpstorm端口63342的修改经历
  • 原文地址:https://www.cnblogs.com/flower-dance/p/14331853.html
Copyright © 2011-2022 走看看