#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