Вызов метода Invoke асинхронно без блокировки основного потока

#java #spring #multithreading #spring-boot #asynchronous

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

Вопрос:

У меня есть сценарий, в котором приложение spring-boot должно загрузить файл из нижестоящего приложения и передать его клиенту. API также необходимо обновить флаг чтения в базе данных, не блокируя ответ (основной поток).

Базовый вариант использования async — это то, о чем я подумал и реализовал в соответствующем API. Но я получаю поведенческую проблему с @Async. Аннотация способна порождать новый поток, но она блокирует основной поток и удерживает ответ. Ожидалось, что он вернется без удержания основного потока. На самом деле, асинхронное обновление является последней операцией основного потока, и я предполагаю, что из-за этого @Async блокирует основной поток.

Кто-нибудь, пожалуйста, может предложить лучшее решение этого сценария.

Вызывающий класс

 ResponseEntity<byte[]> parsedResponse = retrieverService.retrieve(id,"html");

retrieverService.update(id);

return parsedResponse;
  

Асинхронный метод

 @Override
@Async("updateTaskExecutor")
public void update(String id) {
    LOG.info("Updating data for metaTagId: {}", id);
    db.updateReadFlag(id);
}
  

Асинхронная конфигурация

 @Configuration
@EnableAsync
public class AsyncConfiguration {

    @Bean(name = "updateTaskExecutor")
    public Executor updateTaskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(100);
        executor.setMaxPoolSize(100);
        executor.setQueueCapacity(100);
        executor.setThreadNamePrefix("UpdateTaskClient-");
        executor.initialize();
        return executor;
    }
}
  

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

1. Если он содержит основной поток, он не является асинхронным. Откуда вы знаете, что он блокирует основной поток?

2. @M.Deinum Я использовал отладчик, чтобы приостановить действие в асинхронном методе, и я ожидал ответа. Ответ не пришел, пока я не возобновил работу отладчика. Следовательно, это блокировало основной поток.

3. Таким образом, он не является асинхронным, и ваша асинхронная конфигурация не работает. Как я уже говорил, если он выполняется, он не является асинхронным.

4. @M.Deinum , но я вижу другое имя потока (UpdateTaskClient -) в журналах. Возможно ли, что создается новый поток, но его работа синхронизирована с основным потоком?

5. Также @M. Deinum, не могли бы вы помочь мне исправить асинхронные конфигурации

Ответ №1:

Конфигурации были правильными. Я использовал отладчик для проверки параллелизма. Как предложено @M. Deinum, это неправильный способ проверки параллелизма. После использования Thread.sleep() я смог увидеть, что асинхронные вызовы работают так, как ожидалось. Я могу отправить ответ обратно, выполняя запрос на обновление асинхронно.

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

1. где вы переводите основной поток в спящий режим после вызова db.updateReadFlag(id); ? CountDownLatch может быть лучшим вариантом, чем sleep