java - Spring Boot:我们可以为每个请求设置单独的线程池吗?
问题描述
我已经使用 Spring Boot @Async 为我的应用程序中的方法实现了异步执行。我有一个带有 20 个线程的自定义线程池。在 for 循环中调用 async 方法 30 次。
每个单独的请求都是异步执行的,但是当我从浏览器同时向我的 API 发出两个不同的请求时,第一个请求正在执行,然后是第二个请求。不是两个请求并行执行相同的方法。
我想当第一个请求到达应用程序时,它开始执行异步方法,并且由于它正在执行 30 次并且我的池有 20 个线程,所有线程都忙于执行第一个请求。因此,即使第二个请求也因为线程池繁忙而执行,另一个请求正在等待线程池中的线程空闲。
我们可以为每个单独的请求设置单独的线程池吗?或者我们可以使每个请求的执行独立于其他请求处理的任何方式。
这是我的代码示例。
@SpringBootApplication
@EnableAsync
public class AppBootStrap
{
public static void main(String[] args)
{
SpringApplication.run(AppBootStrap.class, args);
}
@Bean
public AsyncTaskService asyncTaskService() {
return new AsyncTaskService();
}
@Bean(name="customExecutor")
public Executor taskExecutor() {
ThreadPoolTaskExecutor poolExecutor = new ThreadPoolTaskExecutor();
poolExecutor.setCorePoolSize(10);
poolExecutor.setMaxPoolSize(20);
poolExecutor.setThreadNamePrefix("customPoolExecutor");
poolExecutor.initialize();
return poolExecutor;
}
}
**Controller Class:**
@RestController
public class TaskController
{
@Autowired
private TaskService taskService;
@RequestMapping("/performAction")
public void performAction() {
taskService.performAction();
}
}
**Service class**
@Service
public class TaskService
{
@Autowired
private AsyncTaskService asyncTaskService;
public void performAction()
{
for(int i = 0; i < 30; i++) {
asyncTaskService.greetings(i);
}
}
}
**Async Method Class**
public class AsyncTaskService
{
@Async
public void greetings(Integer i)
{
try
{
Thread.sleep(500 * (i + 10));
}
catch (InterruptedException e)
{
e.printStackTrace();
}
System.out.println("Welcome to Async Service: " + i);
}
}
解决方案
@Bean(name = "apiTaskExecutor")
public ThreadPoolTaskExecutor apiTaskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(20);
executor.setMaxPoolSize(100);
executor.setQueueCapacity(50);
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.initialize();
return executor;
}
@Bean(name = "lruTaskExecutor")
public ThreadPoolTaskExecutor lruTaskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(100);
executor.setMaxPoolSize(200);
executor.setQueueCapacity(500);
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.initialize();
return executor;
}
这样做的方法是使用不同的限定符名称创建两个不同的线程池。(如上图)
@Autowired
@Qualifier("apiTaskExecutor")
private ThreadPoolTaskExecutor apiTaskExecutor;
然后使用您给定的限定符自动装配所需的池。您也可以使用@Async
注解代替自动装配。我更喜欢这种方式。
如果我没记错的话,这种为不同任务使用不同线程池的方式被称为隔板模式。
推荐阅读
- ios - 在 iOS 上使用 edgeSDK 包装器部署微服务时的 imagePath 和 apiRootUrl 值是什么?如何设置它们?
- javascript - 输入单词后如何在文本框中设置光标?
- c++-cli - 无法构建全新的 CLR 类库项目:缺少 MSCOREE.lib
- r - 如何对齐谷歌地图经度纬度的ggmap CRS
- javascript - 使用 typeScript 获取本地 JSON 文件。我在静态页面中遇到跨源错误
- php - 使用 Laravel assertDatabaseHas 和浮点列进行单元测试
- python - Dialogflow 查询 HTTP 请求
- vba - 将文件夹中所有文件的数据复制并粘贴到同一文件夹中的主文件
- javascript - 如何将二进制视频数据保存到 azure blob?
- python - 将熊猫列的一部分复制到同一列的其他部分?