Как использовать асинхронность при загрузке Spring?

#spring #multithreading #spring-boot #rest #asynchronous

#весна #многопоточность #spring-boot #отдых #асинхронный

Вопрос:

Ниже приведен мой код.

В приведенном ниже коде разные идентификаторы потоков не создаются.

Выходные данные имеют тот же идентификатор потока.

 @Controller
@RequestMapping(value = "/Main")
public class MyController 
{
   @Autowired
   private MyService myService;
   
   @PostMapping("/Sub")
   @ResponseBody
   public String readInput(@RequestBody String name)
   {
       for (int i = 0;i<5;i  )
       {
           myService.asyncMethod();
       }
       return "Success";
   }
}
 

В приведенном ниже коде разные идентификаторы потоков не создаются.

 @Repository
@Configuration
@EnableAsync
public class MyService {

    @Bean(name = "threadPoolTaskExecutor")
    public Executor threadPoolTaskExecutor() {
      return new ThreadPoolTaskExecutor();
    }
     
    @Async("threadPoolTaskExecutor")
    public void asyncMethod() {
      System.out.println("Thread "   Thread.currentThread().getId()  " is running");
    }
}
 

Ответ №1:

Прежде всего, невозможно судить, используется ли пул потоков по идентификатору потока. Вы можете установить префикс потока и судить по журналу

  1. Настройка пула потоков
 @Slf4j
@Configuration
public class ThreadExecutorConfig {

    @Autowired
    private ThreadPoolProperties threadPoolProperties;

    @Bean(name = "taskExecutor")
    public ExecutorService executorService() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(threadPoolProperties.getCorePoolSize());
        executor.setMaxPoolSize(threadPoolProperties.getMaxPoolSize());
        executor.setQueueCapacity(threadPoolProperties.getQueueSize());
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        executor.setThreadNamePrefix("myThread-");
        executor.initialize();
        log.info("threadPoolConfig;corePoolSize:[{}];maxPoolSize:[{}];queueSize:[{}]",
                threadPoolProperties.getCorePoolSize(),
                threadPoolProperties.getMaxPoolSize(),
                threadPoolProperties.getQueueSize());
        return executor.getThreadPoolExecutor();
    }
}
 
  1. Используйте @Async аннотации к методам
     @Async(value = "taskExecutor")
    @Override
    public void asyncSave(OperationLogModel entity) {
        if (log.isDebugEnabled()) {
            log.debug("thread:{};entity:{}", Thread.currentThread().getName(), entity.toString());
        }
        entity.setCreateTime(LocalDateTime.now());
        super.save(entity);
    }
 
  1. Просмотр журнала
    введите описание изображения здесь

Ответ №2:

Хороший вопрос! Ответ находится в ThreadPoolTaskExecutor . По умолчанию corePoolSize используется единица.

 @Bean(name = "threadPoolTaskExecutor")
public Executor threadPoolTaskExecutor() {
    ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
    threadPoolTaskExecutor.setCorePoolSize(3);//or any (positive) integer that suits you.
    return threadPoolTaskExecutor;
} 
 

.. будет вести себя так, как мы ожидаем:

 Thread 127 is running
Thread 128 is running
Thread 128 is running
Thread 129 is running
Thread 127 is running
 

Комментарии:

1. Даже после установки размера основного пула (до 10), он по-прежнему печатает тот же идентификатор потока!

2. Попробуйте добавить Thread.sleep(1000); asyncMethod . @user2488578