// 查询文章
public String selectArticle() {
// TODO 模拟文章查询操作
System.out.println(“查询任务线程”+Thread.currentThread().getName());
return “文章详情”;
}
// 文章阅读量+1
@Async
public void updateReadCount() {
// TODO 模拟耗时操作
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(“更新任务线程”+Thread.currentThread().getName());
}
}
Controller层:
@RestController
public class AsyncTestController {
@Autowired
private ArticleServiceImpl articleService;
/**
- 模拟获取文章后阅读量+1
*/
@PostMapping(“/article”)
public String getArticle() {
// 查询文章
String article = articleService.selectArticle();
// 阅读量+1
articleService.updateReadCount();
System.out.println(“文章阅读业务执行完毕”);
return article;
}
}
测试结果: 我们可以感受到接口响应速度大大提升, 而且从日志中key看到两个执行任务是在不同的线程中执行的
3. 自定义线程池执行异步方法
================
SpringBoot为我们默认提供了线程池(SimpleAsyncTaskExecutor)来执行我们的异步方法, 我们也可以自定义自己的线程池.
第一步配置自定义线程池
@EnableAsync // 开启多线程, 项目启动时自动创建
@Configuration
public class AsyncConfig {
@Bean(“customExecutor”)
public ThreadPoolTaskExecutor asyncOperationExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
// 设置核心线程数
executor.setCorePoolSize(8);
// 设置最大线程数
executor.setMaxPoolSize(20);
// 设置队列大小
executor.setQueueCapacity(Integer.MAX_VALUE);
// 设置线程活跃时间(秒)
executor.setKeepAliveSeconds(60);
// 设置线程名前缀+分组名称
executor.setThreadNamePrefix(“AsyncOperationThread-”);
executor.setThreadGroupName(“AsyncOperationGroup”);
// 所有任务结束后关闭线程池
executor.setWaitForTasksToCompleteOnShutdown(true);
// 初始化
executor.initialize();
return executor;
}
}
第二步, 在@Async注解上指定执行的线程池即可
// 文章阅读量+1
@Async(“customExecutor”)
public void updateReadCount() {
// TODO 模拟耗时操作
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(“更新文章阅读量线程”+Thread.currentThread().getName());
}
5. 如何捕获(无返回值的)异步方法中的异常
=======================
以实现AsyncConfigurer接口的getAsyncExecutor方法和getAsyncUncaughtExceptionHandler方法改造配置类
自定义异常处理类CustomAsyncExceptionHandler
@EnableAsync // 开启多线程, 项目启动时自动创建
@Configuration
public class AsyncConfig implements AsyncConfigurer {
@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
// 设置核心线程数
executor.setCorePoolSize(8);
// 设置最大线程数
executor.setMaxPoolSize(20);
// 设置队列大小
executor.setQueueCapacity(Integer.MAX_VALUE);
// 设置线程活跃时间(秒)
executor.setKeepAliveSeconds(60);
// 设置线程名前缀+分组名称
executor.setThreadNamePrefix(“AsyncOperationThread-”);
executor.setThreadGroupName(“AsyncOperationGroup”);
// 所有任务结束后关闭线程池
executor.setWaitForTasksToCompleteOnShutdown(true);
// 初始化
executor.initialize();
return executor;
}
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return new CustomAsyncExceptionHandler();
}
}
public class CustomAsyncExceptionHandler implements AsyncUncaughtExceptionHandler {
@Override
public void handleUncaughtException(Throwable throwable, Method method, Object… obj) {
System.out.println(“异常捕获---------------------------------”);
System.out.println("Exception message - " + throwable.getMessage());
System.out.println("Method name - " + method.getName());
for (Object param : obj) {
System.out.println("Parameter value - " + param);
}
System.out.println(“异常捕获---------------------------------”);
}
}
5. 如何获取(有返回值)异步方法的返回值
======================
使用Future类及其子类来接收异步方法返回值
注意:
-
无返回值的异步方法抛出异常不会影响Controller的主要业务逻辑
-
有返回值的异步方法抛出异常会影响Controller的主要业务逻辑
最后
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Java工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。
因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!
如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
片转存中…(img-MEFIP8RY-1715071979980)]
[外链图片转存中…(img-iAY9BleM-1715071979981)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!
如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!