《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》,点击传送门,即可获取!
public class TaskPoolConfig {
@Bean
public Executor taskExecutor1() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(2);
executor.setMaxPoolSize(2);
executor.setQueueCapacity(10);
executor.setKeepAliveSeconds(60);
executor.setThreadNamePrefix(“executor-1-”);
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
return executor;
}
@Bean
public Executor taskExecutor2() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(2);
executor.setMaxPoolSize(2);
executor.setQueueCapacity(10);
executor.setKeepAliveSeconds(60);
executor.setThreadNamePrefix(“executor-2-”);
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
return executor;
}
}
注意:这里特地用
executor.setThreadNamePrefix
设置了线程名的前缀,这样可以方便观察后面具体执行的顺序。
第二步:创建异步任务,并指定要使用的线程池名称
@Slf4j
@Component
public class AsyncTasks {
public static Random random = new Random();
@Async(“taskExecutor1”)
public CompletableFuture doTaskOne(String taskNo) throws Exception {
log.info(“开始任务:{}”, taskNo);
long start = System.currentTimeMillis();
Thread.sleep(random.nextInt(10000));
long end = System.currentTimeMillis();
log.info(“完成任务:{},耗时:{} 毫秒”, taskNo, end - start);
return CompletableFuture.completedFuture(“任务完成”);
}
@Async(“taskExecutor2”)
public CompletableFuture doTaskTwo(String taskNo) throws Exception {
log.info(“开始任务:{}”, taskNo);
long start = System.currentTimeMillis();
Thread.sleep(random.nextInt(10000));
long end = System.currentTimeMillis();
log.info(“完成任务:{},耗时:{} 毫秒”, taskNo, end - start);
return CompletableFuture.completedFuture(“任务完成”);
}
}
这里@Async
注解中定义的taskExecutor1
和taskExecutor2
就是线程池的名字。由于在第一步中,我们没有具体写两个线程池Bean的名称,所以默认会使用方法名,也就是taskExecutor1
和taskExecutor2
。
第三步:写个单元测试来验证下,比如下面这样:
@Slf4j
@SpringBootTest
public class Chapter77ApplicationTests {
@Autowired
private AsyncTasks asyncTasks;
@Test
public void test() throws Exception {
long start = System.currentTimeMillis();
// 线程池1
CompletableFuture task1 = asyncTasks.doTaskOne(“1”);
CompletableFuture task2 = asyncTasks.doTaskOne(“2”);
CompletableFuture task3 = asyncTasks.doTaskOne(“3”);
// 线程池2
CompletableFuture task4 = asyncTasks.doTaskTwo(“4”);
CompletableFuture task5 = asyncTasks.doTaskTwo(“5”);
CompletableFuture task6 = asyncTasks.doTaskTwo(“6”);
// 一起执行
CompletableFuture.allOf(task1, task2, task3, task4, task5, task6).join();
long end = System.currentTimeMillis();
log.info(“任务全部完成,总耗时:” + (end - start) + “毫秒”);
}
}
在上面的单元测试中,一共启动了6个异步任务,前三个用的是线程池1,后三个用的是线程池2。
先不执行,根据设置的核心线程2和最大线程数2,来分析一下,大概会是怎么样的执行情况?
-
线程池1的三个任务,task1和task2会先获得执行线程,然后task3因为没有可分配线程进入缓冲队列
-
线程池2的三个任务,task4和task5会先获得执行线程,然后task6因为没有可分配线程进入缓冲队列
-
任务task3会在task1或task2完成之后,开始执行
-
任务task6会在task4或task5完成之后,开始执行
分析好之后,执行下单元测试,看看是否是这样的:
2021-09-15 23:45:11.369 INFO 61670 — [ executor-1-1] com.didispace.chapter77.AsyncTasks : 开始任务:1
2021-09-15 23:45:11.369 INFO 61670 — [ executor-2-2] com.didispace.chapter77.AsyncTasks : 开始任务:5
2021-09-15 23:45:11.369 INFO 61670 — [ executor-2-1] com.didispace.chapter77.AsyncTasks : 开始任务:4
2021-09-15 23:45:11.369 INFO 61670 — [ executor-1-2] com.didispace.chapter77.AsyncTasks : 开始任务:2
2021-09-15 23:45:15.905 INFO 61670 — [ executor-2-1] com.didispace.chapter77.AsyncTasks : 完成任务:4,耗时:4532 毫秒
2021-09-15 23:45:15.905 INFO 61670 — [ executor-2-1] com.didispace.chapter77.AsyncTasks : 开始任务:6
2021-09-15 23:45:18.263 INFO 61670 — [ executor-1-2] com.didispace.chapter77.AsyncTasks : 完成任务:2,耗时:6890 毫秒
2021-09-15 23:45:18.263 INFO 61670 — [ executor-1-2] com.didispace.chapter77.AsyncTasks : 开始任务:3
2021-09-15 23:45:18.896 INFO 61670 — [ executor-2-2] com.didispace.chapter77.AsyncTasks : 完成任务:5,耗时:7523 毫秒
2021-09-15 23:45:19.842 INFO 61670 — [ executor-1-2] com.didispace.chapter77.AsyncTasks : 完成任务:3,耗时:1579 毫秒
2021-09-15 23:45:20.551 INFO 61670 — [ executor-1-1] com.didispace.chapter77.AsyncTasks : 完成任务:1,耗时:9178 毫秒
2021-09-15 23:45:24.117 INFO 61670 — [ executor-2-1] com.didispace.chapter77.AsyncTasks : 完成任务:6,耗时:8212 毫秒
2021-09-15 23:45:24.117 INFO 61670 — [ main] c.d.chapter77.Chapter77ApplicationTests : 任务全部完成,总耗时:12762毫秒
好了,今天的学习就到这里!如果您学习过程中如遇困难?可以加入我们超高质量的Spring技术交流群,参与交流与讨论,更好的学习与进步!更多Spring Boot教程可以点击直达!,欢迎收藏与转发支持!
本文的完整工程可以查看下面仓库中2.x
目录下的chapter7-7
工程:
最后
现在正是金三银四的春招高潮,前阵子小编一直在搭建自己的网站,并整理了全套的**【一线互联网大厂Java核心面试题库+解析】:包括Java基础、异常、集合、并发编程、JVM、Spring全家桶、MyBatis、Redis、数据库、中间件MQ、Dubbo、Linux、Tomcat、ZooKeeper、Netty等等**
《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》,点击传送门,即可获取!
建自己的网站,并整理了全套的**【一线互联网大厂Java核心面试题库+解析】:包括Java基础、异常、集合、并发编程、JVM、Spring全家桶、MyBatis、Redis、数据库、中间件MQ、Dubbo、Linux、Tomcat、ZooKeeper、Netty等等**
[外链图片转存中…(img-9Fuj6UES-1714657768428)]
《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》,点击传送门,即可获取!