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

Java Spring Boot:我们可以为每个请求提供单独的线程池吗?,java,multithreading,spring-boot,threadpoolexecutor,Java,Multithreading,Spring Boot,Threadpoolexecutor,我已经在应用程序中使用SpringBoot@Async实现了一个方法的异步执行。我有一个20线程的自定义线程池。在for循环中调用异步方法30次 每个请求都是异步执行的,但当我从浏览器同时向API发出两个不同的请求时,第一个请求正在执行,第二个请求正在执行。不是两个请求都并行执行同一个方法 我认为当第一个请求到达应用程序时,它开始执行异步方法,因为它执行了30次,而且我的池有20个线程,所以所有线程都在忙于执行第一个请求。因此,即使是第二个请求也会执行,因为线程池很忙,所以另一个请求正在等待,直

我已经在应用程序中使用SpringBoot@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);
  }
}
@springboot应用程序
@使能同步
公共类AppBootStrap
{
公共静态void main(字符串[]args)
{
run(AppBootStrap.class,args);
}
@豆子
公共AsyncTaskService AsyncTaskService(){
返回新的AsyncTaskService();
}
@Bean(name=“customExecutor”)
公共执行者任务执行者(){
ThreadPoolTaskExecutor poolExecutor=新的ThreadPoolTaskExecutor();
poolExecutor.setCorePoolSize(10);
poolExecutor.setMaxPoolSize(20);
setThreadNamePrefix(“customPoolExecutor”);
poolExecutor.initialize();
返回池执行器;
}
}
**控制器类:**
@RestController
公共类任务控制器
{
@自动连线
私人任务服务任务服务;
@请求映射(“/performAction”)
公开无效执行(){
taskService.performAction();
}
}
**服务等级**
@服务
公共类任务服务
{
@自动连线
专用AsyncTaskService AsyncTaskService;
公开无效执行()
{
对于(int i=0;i<30;i++){
asyncTaskService.问候语(i);
}
}
}
**异步方法类**
公共类异步任务服务
{
@异步的
公共无效问候语(整数i)
{
尝试
{
睡眠(500*(i+10));
}
捕捉(中断异常e)
{
e、 printStackTrace();
}
System.out.println(“欢迎使用异步服务:”+i);
}
}

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

    @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;
}
实现这一点的方法是使用不同的限定符名称创建两个不同的线程池。(如上所示)

然后使用给定的限定符自动连接所需的池。您还可以使用
@Async
注释代替自动布线。我更喜欢这种方式


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

并不是两个请求都并行执行相同的方法。
这是完全错误的,在servlet容器中,每个请求都有自己的线程,因此每种定义都是并行的。但若并没有线程离开ofc。其他请求需要等待,但每个请求总是并行执行。如果您想使用自定义执行器,您应该在异步注释
@async(“customExecutor”)
中提供它的名称,您的话绝对正确。但是在这个场景中,两个diff请求到达服务器,所以执行肯定是并行的,但是当执行到这个特定的逻辑(异步方法执行)时,等待正在发生。对于异步注释,我还添加了自定义执行器。忘记在上面的代码中提及。请更新您的代码,然后使用正确的code@Bean(name=“customExecutor”)@Scope(“prototype”)public Executor taskExecutor(){ThreadPoolTaskExecutor poolExecutor=new ThreadPoolTaskExecutor();poolExecutor.setCorePoolSize(10);poolExecutor.setMaxPoolSize(20);poolExecutor.setthreadnameffix(“customPoolExecutor”);poolExecutor.initialize();返回poolExecutor;}
    @Autowired
    @Qualifier("apiTaskExecutor")
    private ThreadPoolTaskExecutor apiTaskExecutor;