SpringBoot开启异步多线程
前言:
SpringBoot 的异步多线程需要从 java 的多线程基础说起,可以参考 java 多线程实现的三种方式区别。SpringBoot 在此基础上进行了多次封装,所以使用起来非常方便。
一、核心参数说明
ThreadPoolExecutor 是 java 的核心线程池类;Spring 对 ThreadPoolExecutor 进行二次封装形成了 ThreadPoolTaskExecutor,其中几个核心参数除了名字略有改动,核心含义没变,下面说明一下:
- corePoolSize:核心线程池数
- maxPoolSize:最大线程池数
- queueCapacity:线程池队列最大容量
- keepAliveSeconds:允许线程的空闲时间,核心线程外的线程在空闲时间到达后会被销毁
- threadNamePrefix:线程池名的前缀
- rejectedExecutionHandler:拒绝策略
其中拒绝策略是线程达到某种饱和后的线程池的操作策略,总共四种:
- AbortPolicy:如果线程池队列满了丢掉任务并且抛出RejectedExecutionException异常
- DiscardPolicy:如果线程池队列满了,会直接丢掉这个任务并且不会抛出异常
- DiscardOldestPolicy:如果队列满了,会将最早进入队列的任务删掉,再尝试加入队列
- CallerRunsPolicy:如果添加到线程池失败,那么主线程会自己去执行该任务
说明一下几个核心参数和拒绝策略是怎么工作的:
1.核心线程数:m,最大线程数: n(一般 n > m),线程池队列最大容量: j,线程总数: s;
2.线程进场后(s<m),线程会直接启动直到启动的线程数达到核心线程数(s=m);
3.线程继续进场(m<s<m j),线程开始排队,此时启动的线程数不会增加直到队列饱和(s=m j);
4.线程继续进场(m j<s<n j),每进场一个线程,该线程就会启动;直到启动的线程达到最大线程数(s=n j);
5.线程继续进场(s>n j),此时触发拒绝策略;
二、使用说明
首先配置线程池:
-
-
-
public class ThreadPoolConfig {
-
-
//线程池实例名,多个线程池配置需要声明,一个线程池可有可无
-
public Executor executorNormal() {
-
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
-
executor.setCorePoolSize(3);
-
executor.setMaxPoolSize(5);
-
executor.setQueueCapacity(3);
-
executor.setKeepAliveSeconds(60);
-
executor.setThreadNamePrefix("NORMAL--");
-
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
-
executor.initialize();
-
return executor;
-
}
-
}
其次在需要异步的方法上加 @Async 注解:
-
-
-
public class ThreadTaskService {
-
-
//多个线程池配置时需指定配置实例
-
public void task() {
-
log.info("task start...");
-
try {
-
Thread.sleep(3000);
-
} catch (InterruptedException e) {
-
e.printStackTrace();
-
}
-
log.info("task end...");
-
}
-
-
}
异步的调用跟普通 service 方法没区别:
-
-
-
-
public class ThreadTaskController {
-
-
-
ThreadTaskService taskService;
-
-
-
public String getValue() {
-
taskService.task();
-
return "hello...";
-
}
-
}
三、带返回值的异步
要获取异步函数的返回值可以使用 Future,但是Future 的get方法是阻塞的,使用时需要注意。
-
-
public CompletableFuture<String> task() {
-
String result = "000";
-
log.info("task start...");
-
try {
-
Thread.sleep(5000);
-
result = "333";
-
} catch (InterruptedException e) {
-
e.printStackTrace();
-
}
-
log.info("task end...");
-
return CompletableFuture.completedFuture(result);
-
}
-
-
-
-
public class ThreadTaskController {
-
-
ThreadTaskService taskService;
-
-
-
public String getValue() throws ExecutionException, InterruptedException {
-
-
CompletableFuture<String> result = taskService.task();
-
-
log.info("result:{}", result.get()); // get 方法会使主线程阻塞
-
-
return "hello...";
-
}
-
}
四、几种异步失败的情况
1. 异步方法使用static关键词修饰;
2. 缺少 @EnableAsync
注解;
3. 同一个类中,一个方法调用另外一个有@Async注解的方法(原因是@Async注解的方法,是在代理类中执行的);
这篇好文章是转载于:学新通技术网
- 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
- 本站站名: 学新通技术网
- 本文地址: /boutique/detail/tanhfeikef
系列文章
更多
同类精品
更多
-
photoshop保存的图片太大微信发不了怎么办
PHP中文网 06-15 -
Android 11 保存文件到外部存储,并分享文件
Luke 10-12 -
《学习通》视频自动暂停处理方法
HelloWorld317 07-05 -
word里面弄一个表格后上面的标题会跑到下面怎么办
PHP中文网 06-20 -
photoshop扩展功能面板显示灰色怎么办
PHP中文网 06-14 -
微信公众号没有声音提示怎么办
PHP中文网 03-31 -
excel下划线不显示怎么办
PHP中文网 06-23 -
怎样阻止微信小程序自动打开
PHP中文网 06-13 -
excel打印预览压线压字怎么办
PHP中文网 06-22 -
TikTok加速器哪个好免费的TK加速器推荐
TK小达人 10-01