Spring Boot:我们可以为每个请求设置单独的线程池吗?



我已经使用 Spring Boot @Async 在我的应用程序中实现了一种方法的异步执行。我有一个带有 20 个线程的自定义线程池。在 for 循环中调用异步方法 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注释而不是自动接线。我更喜欢这种方式。

如果我没记错的话,这种为不同任务使用不同线程池的方式称为隔板模式。

我认为问题是customExecutor bean是一个单例。这意味着当第二个请求尝试使用此 Bean 时,它会发现 thred 池的所有线程都忙了。您可以尝试使用 @Scope("原型"(注释使 customExecutor Bean 非单例,这将导致每当请求这种类型的 Bean 时实例化一个新注释。

最新更新