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/addDB2021-01-26 18:19:01,341 [http-nio-8082-exec-3] INFO (LogAspect.java:38)- HTTP_METHOD : GET2021-01-26 18:19:01,341 [http-nio-8082-exec-3] INFO (LogAspect.java:39)- IP : 0:0:0:0:0:0:0:12021-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/addDB2021-01-26 18:19:01,922 [http-nio-8082-exec-4] INFO (LogAspect.java:38)- HTTP_METHOD : GET2021-01-26 18:19:01,923 [http-nio-8082-exec-4] INFO (LogAspect.java:39)- IP : 0:0:0:0:0:0:0:12021-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/addDB2021-01-26 18:19:02,559 [http-nio-8082-exec-2] INFO (LogAspect.java:38)- HTTP_METHOD : GET2021-01-26 18:19:02,559 [http-nio-8082-exec-2] INFO (LogAspect.java:39)- IP : 0:0:0:0:0:0:0:12021-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了,线程池的参数可以根据⾃⼰项⽬的实际情况调整,不懂线程池的可以去看看我写的《》到此整合异步注解完成作者:彼岸舞时间:2021\\01\\26内容关于:SpringBoot
本⽂来源于⽹络,只做技术分享,⼀概不负任何责任