目录
- 前言
- 一、异步调用实现
- 二、@Async整合线程池
前言
- @Async实际就是多线程封装的
- 异步线程执行方法有可能会非常消耗cpu的资源,所以大的项目建议使用Mq异步实现
一、异步调用实现
- 1.启动类需要添加注解
@EnableAsync
@SpringBootApplication
@EnableAsync
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class);
}
}
- 2.需要执行异步的方法上加上注解
@Async
- 注意失效问题:如果异步注解写当前自己类,有可能aop会失效,无法拦截注解,最终导致异步注解失效,需要经过代理类调用接口;所以需要将异步的代码单独抽取成一个类调用接口
@RestController
@Slf4j
public class MemberService {
@Autowired
private MemberServiceAsync memberServiceAsync;
@RequestMapping("/addMember")
public String addMember() {
// 1.数据库插入数据
log.info(">01<");
memberServiceAsync.sms();
log.info(">04<");
return "用户注册成功";
}
}
@Component
@Slf4j
public class MemberServiceAsync {
@Async
public String sms() {
log.info(">02<");
try {
log.info(">正在发送短信..<");
Thread.sleep(3000);
} catch (Exception e) {
}
log.info(">03<");
return "短信发送完成!";
}
}

二、@Async整合线程池
- 1.在第一点的例子中虽然我们实现了异步多线程,但是还有缺点
- 每次都重新开启一个线程,这样非常消耗资源影响效率
- 我们需要整合线程池来优化,提高程序的性能
八、SpringBoot整合多线程异步前言一、异步调用实现二、@Async整合线程池
- 2.项目结构
- 3.ThreadPoolConfig
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;
}
}
- 4.在@Async()注解中配置属性"taskExecutor"
@Component
@Slf4j
public class MemberServiceAsync {
@Async("taskExecutor")
public String sms() {
log.info(">02<");
try {
log.info(">正在发送短信..<");
Thread.sleep(3000);
} catch (Exception e) {
}
log.info(">03<");
return "短信发送完成!";
}
/**
* 线程池
*/
}