Как Java Spring Async управляет потоками?

Я хочу написать приложение 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 по-прежнему резервирует рабочий поток для ожидания значения, возвращаемого службой, или рабочий поток возвращается в пул потоков, пока служба не завершит свою работу?

Спасибо.

Не могли бы вы добавить больше деталей в свой пост? Какой вариант использования? Это действительно так работает? Потому что это выглядит странно. Если вы хотите обработать что-то асинхронно, почему тогда вы ждете ответа от асинхронного метода? Вы должны вызвать метод async и вернуть что-то вроде 200 202 правильно, не дожидаясь завершения метода async.

Sergei Sirik 04.01.2019 23:50

Вы прочтите документацию? docs.spring.io/spring/docs/5.1.x/spring-framework-reference/‌…

Andreas 05.01.2019 01:40

Если вам нужна действительно асинхронная архитектура, вам следует использовать такие библиотеки, как RxJava и Project Reactor.

Prashant Pandey 05.01.2019 06:25

@SergeiSirik Код выглядит странно, потому что это всего лишь образец. Замените предоставленный код чем-нибудь понятным. Но структура такая же.

Ertai87 07.01.2019 17:45

@Andreas Эта документация не отвечает на вопрос. Вопрос в том, что происходит с потоком, который использует контроллер при вызове CompleteableFuture.get ()?

Ertai87 07.01.2019 17:46

@ Ertai87 Как насчет того, чтобы показать код контроллера при только что упомянутом вызове get()? Код в вопросе не компилируется, потому что getString() возвращает CompleteableFuture<String>, но вызывающий ожидает String. Покажите код, о котором вы действительно спрашиваете.

Andreas 07.01.2019 22:36

@Andreas Обновлено.

Ertai87 07.01.2019 22:37

@ Ertai87 Javadoc из CompletableFuture.get() говорит: "Ждет, если необходимо для завершения этого будущего, а затем возвращает свой результат". Какую часть «ждать» вы не поняли? Нить усыпляют до готовности результата. Поток нет возвращается в пул потоков. Как это могло произойти?

Andreas 07.01.2019 22:39

Если вы хотите, чтобы поток обработки запросов был освобожден для обработки других запросов, вам необходимо заставить контроллер выполнять асинхронную обработку, как описано в руководство.

Andreas 07.01.2019 22:42

@Andreas Я недостаточно знаю о параллельном программировании и потоковой передаче, чтобы понять, почему это / не может / быть, и я понимаю, что аналогичные функции на других языках работают так (в частности, NodeJS, хотя я недостаточно знаю об этом язык, чтобы знать, что меня обижали, когда мне это объяснили)

Ertai87 07.01.2019 22:43

В других языках это тоже делается на уровне контроллера, а не на уровне сервиса.

Andreas 07.01.2019 22:45
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
2
11
1 923
1

Ответы 1

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 ()), будет ли это блокировать поток, если будущее не завершено?

Ertai87 07.01.2019 17:56

Да, контроллер делает ждет, так как контроллер вызывает get(), который ждет.

Andreas 07.01.2019 22:43

@ Ertai87 Да, когда вы вызываете get() на Future, а вычисление недоступно, вызов блокируется.

Adam Siemion 08.01.2019 00:36

Другие вопросы по теме