java - @Async 指定的执行器是否适用于 CompletableFuture.supplyAsync(supplier)?
问题描述
我有一个执行人,
@Bean("someExecutor")
public Executor someExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(2);
executor.setMaxPoolSize(2);
executor.setQueueCapacity(500);
executor.setThreadNamePrefix("AsyncMethod-");
executor.initialize();
return executor;
}
和一个异步方法。
@Async("someExecutor")
public Future<List<String>> someMethod(){
return CompletableFuture.supplyAsync(() -> {
//long time job
return listGeneratedByLongTimeJob;
});
}
Spring 会为 someMethod 使用 someExecutor 吗?如何?
我知道supplierAsync(supplier)的一个重载方法是supplierAsync(supplier, executor),下面的代码怎么样?
@Autowired("someExecutor")
private Executor executor;
@Async()
public Future<List<String>> someMethod(){
return CompletableFuture.supplyAsync(() -> {
//long time job
return listGeneratedByLongTimeJob;
}, executor);
}
谢谢。
解决方案
好吧,这需要一段时间才能弄清楚,在进入两个场景之前,我们需要讨论一下ForkJoinPool
来自 java.util.concurrent.CompletableFuture 文档
所有没有显式 Executor 参数的异步方法都使用 ForkJoinPool.commonPool()执行(除非它不支持至少两个并行级别,在这种情况下,会创建一个新线程来运行每个任务)。为了简化监控、调试和跟踪,所有生成的异步任务都是标记接口 CompletableFuture.AsynchronousCompletionTask 的实例。
因此,当您每次调用时CompletableFuture.supplyAsync(Supplier s)
,供应商将由ForkJoinPool
线程执行,现在让我们开始案例 1
情况1:
为了清楚起见,我添加了一些sysout
语句来打印线程名称
@Async("someExecutor")
public Future<String> asyncService() {
System.out.println();
System.out.println(Thread.currentThread().getName()+" - "+Thread.currentThread().getThreadGroup());
System.out.println();
return CompletableFuture.supplyAsync(()->{
System.out.println(Thread.currentThread().getName()+" - "+Thread.currentThread().getThreadGroup());
return "hello";
});
}
输出:
AsyncMethod-1 - java.lang.ThreadGroup[name=main,maxpri=10]
ForkJoinPool.commonPool-worker-1 - java.lang.ThreadGroup[name=main,maxpri=10]
在这种情况下asyncService()
,由AsyncMethod-1
线程执行,供应商 insupplyAsync()
由ForkJoinPool
案例2:
@Autowired
private Executor someExecutor;
@Async
public Future<String> asyncService() {
System.out.println();
System.out.println(Thread.currentThread().getName()+" - "+Thread.currentThread().getThreadGroup());
System.out.println();
return CompletableFuture.supplyAsync(()->{
System.out.println(Thread.currentThread().getName()+" - "+Thread.currentThread().getThreadGroup());
return "hello";
},someExecutor);
}
输出:
AsyncMethod-1 - java.lang.ThreadGroup[name=main,maxpri=10]
AsyncMethod-2 - java.lang.ThreadGroup[name=main,maxpri=10]
在第二种情况下asyncService()
,方法和供应商supplyAsync()
都使用来自someExecutor pool
默认情况下,Spring 使用 SimpleAsyncTaskExecutor 来实际运行这些方法,但我们在 config using docsasync
中覆盖了它someExecutor
@EnableAsync
默认情况下,Spring 将搜索关联的线程池定义:要么是上下文中唯一的 TaskExecutor bean,要么是名为“taskExecutor”的 Executor bean。如果两者都无法解析,则将使用 SimpleAsyncTaskExecutor 来处理异步方法调用。
注意:如果您没有@EnableAsync
配置类,您将得到不同的结果,我将在 gitHub 中上传此代码并在此处添加链接
推荐阅读
- javascript - 将 LI 添加到 UL 顶部(EJS、MONGO、Node[Express])
- sql - 如何在 MS SQL 中将分组记录合并为一行
- c++ - 将 .txt 文件中的数据读入结构
- vue.js - 插件的 globalUIComponent 在构建期间执行 - 如何避免它?
- go - 通过队列发送哨兵追踪
- express - 错误:找不到模块 './models/book' 需要堆栈:
- matlab - 从顶点递归采样三角形?
- php - 为 2 个模型颁发 sanctum 令牌,以验证 API 请求(不是默认用户模型)
- flutter - 即使是无效用户也能登录成功
- javascript - 如何为 Ruby On Rails 编写 JavaScript?