整合多线程异步

  • 异步调用
  • 使用@Async实现异步调用
  • @Async失效问题
  • 使用@Async整合线程池


异步调用

单线程情况下,接口响应给客户端时间变慢 ,异步线程会单独开启一个线程,提高响应效率。
创建类

@RequestMapping("/add")
    public String add(){
       log.info(">01<");
       sms();
       log.info(">04<");
       return "用户注册成功";
   }
   public String sms(){
       log.info(">02<");
       try{
           log.info(">正在发送信息。。<");
           Thread.sleep(3000);
       }catch (Exception e){

       }
       log.info(">03<");
       return "短信发送完成";
   }

发现加载网页变慢

spring boot 并发线程数 springboot多线程高并发_线程池


可以看到单线程环境下的执行顺序1,2,3,4。

spring boot 并发线程数 springboot多线程高并发_Async_02


开启一个新线程发送短信。

spring boot 并发线程数 springboot多线程高并发_spring boot_03


发现执行顺序发生变化1,4,2,3

spring boot 并发线程数 springboot多线程高并发_spring boot 并发线程数_04

使用@Async实现异步调用

使用异步注解
启动加上@EnableAsync ,需要执行异步方法上加入@Async
异步应用场景
@Async实际就是多线程封装的
异步线程执行方法有可能会非常消耗cpu的资源,所以大的项目建议使用Mq异步实现。

@Async失效问题

使用@Async注解。

spring boot 并发线程数 springboot多线程高并发_spring boot_05


发现并没作用,程序又成单线程了。

spring boot 并发线程数 springboot多线程高并发_spring boot_06


注意:如果异步注解写当前自己类,有可能aop会失效,无法拦截注解,最终导致异步注解失效,需要经过代理类调用接口;所以需要将异步的代码单独抽取成一个类调用接口。

新建接口类

@Component
@Slf4j
public class Asyns {
    @Async
    public String sms() {
        log.info(">02<");
        try {
            log.info(">正在发送信息。。<");
            Thread.sleep(3000);
        } catch (Exception e) {

        }
        log.info(">03<");
        return "短信发送完成";
    }

spring boot 并发线程数 springboot多线程高并发_ci_07


可以看到成果。

spring boot 并发线程数 springboot多线程高并发_Async_08

使用@Async整合线程池

创建线程池
api配置
下面配置最多创建3个线程,然后不停复用。

@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;
    }

spring boot 并发线程数 springboot多线程高并发_ci_09


结果

spring boot 并发线程数 springboot多线程高并发_spring boot_10