一 自定义线程池
package com.example.demo.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.ThreadPoolExecutor;
/**
* @Author cc
* @Date 2020/7/28 10:45
* @Version 1.0
* 线程池配置
*/
@Configuration
@EnableAsync
public class ThreadPoolTaskConfig {
/**
* 默认情况下,在创建了线程池后,线程池中的线程数为0,当有任务来之后,就会创建一个线程去执行任务,
* 当线程池中的线程数目达到corePoolSize后,就会把到达的任务放到缓存队列当中;
* 当队列满了,就继续创建线程,当线程数量大于等于maxPoolSize后,开始使用拒绝策略拒绝
*/
/** 核心线程数(默认线程数) */
private static final int corePoolSize = 15;
/** 最大线程数 */
private static final int maxPoolSize = 50;
/** 允许线程空闲时间(单位:默认为秒) */
private static final int keepAliveTime = 60;
/** 缓冲队列大小 */
private static final int queueCapacity = 100;
/** 线程池名前缀 */
private static final String threadNamePrefix = "Async-Service-";
@Bean("taskExecutor") // bean的名称,默认为首字母小写的方法名
public ThreadPoolTaskExecutor taskExecutor(){
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(corePoolSize);
executor.setMaxPoolSize(maxPoolSize);
executor.setQueueCapacity(queueCapacity);
executor.setKeepAliveSeconds(keepAliveTime);
executor.setThreadNamePrefix(threadNamePrefix);
// 线程池对拒绝任务的处理策略
// CallerRunsPolicy:由调用线程(提交任务的线程)处理该任务
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
// 初始化
executor.initialize();
return executor;
}
}
二 异步执行方法
启动类添加@EnableAsync注解
@SpringBootApplication
@EnableAsync
@EnableScheduling
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
service层方法
@Service
public class AsyncService {
Logger log = LoggerFactory.getLogger(AsyncService.class);
// 发送提醒短信 1
@Async("taskExecutor")// 指定线程池,也可以直接写@Async
public void sendMessage1() throws InterruptedException {
log.info("发送短信方法---- 1 执行开始");
Thread.sleep(5000); // 模拟耗时
log.info("发送短信方法---- 1 执行结束" + new Date());
}
// 发送提醒短信 2
@Async("taskExecutor") // 指定线程池,也可以直接写@Async
public void sendMessage2() throws InterruptedException {
log.info("发送短信方法---- 2 执行开始");
Thread.sleep(2000); // 模拟耗时
log.info("发送短信方法---- 2 执行结束" + new Date());
}
// 发送提醒短信 3
@Async("taskExecutor") // 指定线程池,也可以直接写@Async
public Future<String> sendMessage3() throws InterruptedException {
log.info("发送短信方法---- 3 执行开始"+ new Date());
Thread.sleep(2000); // 模拟耗时
log.info("发送短信方法---- 3 执行结束" + new Date());
return new AsyncResult<String>("发送短信3");
}
// 发送提醒短信 3
@Async("taskExecutor") // 指定线程池,也可以直接写@Async
public Future<String> sendMessage4() throws InterruptedException {
log.info("发送短信方法---- 4 执行开始"+ new Date());
Thread.sleep(2000); // 模拟耗时
log.info("发送短信方法---- 4 执行结束" + new Date());
return new AsyncResult<String>("发送短信4");
}
}
三 多线程返回结果
@GetMapping("/b")
public String b() throws InterruptedException, ExecutionException {
Future<String> sendMessage3 = asyncService.sendMessage3();
Future<String> sendMessage4 = asyncService.sendMessage4();
String result="hello world";
System.out.println(new Date());
while (!sendMessage3.isDone() || !sendMessage4.isDone()){
Thread.sleep(50);
result += sendMessage3.get();
result += sendMessage4.get();
}
System.out.println(new Date());
return result;
}
日志
Thu Aug 06 10:46:33 CST 2020
2020-08-06 10:46:33.703 INFO 9688 --- [Async-Service-3] com.example.demo.service.AsyncService : 发送短信方法---- 3 执行开始Thu Aug 06 10:46:33 CST 2020
2020-08-06 10:46:33.703 INFO 9688 --- [Async-Service-2] com.example.demo.service.AsyncService : 发送短信方法---- 4 执行开始Thu Aug 06 10:46:33 CST 2020
2020-08-06 10:46:35.704 INFO 9688 --- [Async-Service-2] com.example.demo.service.AsyncService : 发送短信方法---- 4 执行结束Thu Aug 06 10:46:35 CST 2020
2020-08-06 10:46:35.704 INFO 9688 --- [Async-Service-3] com.example.demo.service.AsyncService : 发送短信方法---- 3 执行结束Thu Aug 06 10:46:35 CST 2020
Thu Aug 06 10:46:35 CST 2020
接口返回