Я хочу написать приложение Spring Boot с учетом неблокирующих запросов. В общем, мои методы контроллера - это однострочные методы, которые просто вызывают метод службы, а затем возвращают его, например:
@RestController
class myController {
...
@GetMapping("/")
public String getString(){
return service.getString().get();
}
}
Скажем, у меня есть реализация службы, которая выглядит примерно так:
@Service
class myService{
...
@Async
public CompleteableFuture<String> getString(){
return "Hello World!";
}
}
(Предположим, я где-то включил @EnableAsync, и предположим, что код контроллера изменен для обработки CompleteableFutures путем извлечения значения String и его возврата)
Когда мой контроллер вызывает мою службу, Java по-прежнему резервирует рабочий поток для ожидания значения, возвращаемого службой, или рабочий поток возвращается в пул потоков, пока служба не завершит свою работу?
Спасибо.
Вы прочтите документацию? docs.spring.io/spring/docs/5.1.x/spring-framework-reference/…
Если вам нужна действительно асинхронная архитектура, вам следует использовать такие библиотеки, как RxJava и Project Reactor.
@SergeiSirik Код выглядит странно, потому что это всего лишь образец. Замените предоставленный код чем-нибудь понятным. Но структура такая же.
@Andreas Эта документация не отвечает на вопрос. Вопрос в том, что происходит с потоком, который использует контроллер при вызове CompleteableFuture.get ()?
@ Ertai87 Как насчет того, чтобы показать код контроллера при только что упомянутом вызове get()? Код в вопросе не компилируется, потому что getString() возвращает CompleteableFuture<String>, но вызывающий ожидает String. Покажите код, о котором вы действительно спрашиваете.
@Andreas Обновлено.
@ Ertai87 Javadoc из CompletableFuture.get() говорит: "Ждет, если необходимо для завершения этого будущего, а затем возвращает свой результат". Какую часть «ждать» вы не поняли? Нить усыпляют до готовности результата. Поток нет возвращается в пул потоков. Как это могло произойти?
Если вы хотите, чтобы поток обработки запросов был освобожден для обработки других запросов, вам необходимо заставить контроллер выполнять асинхронную обработку, как описано в руководство.
@Andreas Я недостаточно знаю о параллельном программировании и потоковой передаче, чтобы понять, почему это / не может / быть, и я понимаю, что аналогичные функции на других языках работают так (в частности, NodeJS, хотя я недостаточно знаю об этом язык, чтобы знать, что меня обижали, когда мне это объяснили)
В других языках это тоже делается на уровне контроллера, а не на уровне сервиса.




When my controller calls my service, does Java still reserve a worker thread to wait on the return value from the Service
Нет, ваш контроллер не ждет, метод метода @Async вызывается асинхронно.
or is the worker thread returned to the thread pool until the service completes its work?
По умолчанию, когда вызывается метод @Async, Spring использует SimpleAsyncTaskExecutor, который запускает новый поток для каждого вызова, поэтому пул потоков не используется. Однако вы можете предоставить свой собственный исполнитель задач или использовать ThreadPoolTaskExecutor - Детали.
Я не думаю, что это ответ на вопрос. Насколько я понимаю, запускается новый поток для выполнения асинхронного метода. Я хочу знать, когда вызывающий хочет получить значение из службы (например, вызывающий вызывает CompleteableFuture.get ()), будет ли это блокировать поток, если будущее не завершено?
Да, контроллер делает ждет, так как контроллер вызывает get(), который ждет.
@ Ertai87 Да, когда вы вызываете get() на Future, а вычисление недоступно, вызов блокируется.
Не могли бы вы добавить больше деталей в свой пост? Какой вариант использования? Это действительно так работает? Потому что это выглядит странно. Если вы хотите обработать что-то асинхронно, почему тогда вы ждете ответа от асинхронного метода? Вы должны вызвать метод async и вернуть что-то вроде 200 202 правильно, не дожидаясь завершения метода async.