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