Использование ответа субъекта в текущем процессе субъекта

0

Вопрос

Я в замешательстве по поводу того, как я должен разрешить этот сценарий неблокирующим способом.

Рассмотрим двух действующих лиц Actor1 и Actor2

Внутри Actor1

Map<Int, Int> foo() {
     List<String> finalList = foo_2();
     Map<Int, Int> finalMap = // do stuff with finalList to get Map<Int, Int>;

     return finalMap;
}

List<String> foo_2() {
    
     CompletableFuture<List<String>> Querylist = ask(Actor2)
     Querylist.get();
     
     return QueryList;
}

В настоящее время в пределах foo_2, Querylist.get() это блокирующий вызов. Я хочу как-то решить эту проблему неблокирующим способом. Я создал адаптер сообщений для Actor2 внутри Actor1 так что любые сообщения, которые Actor2 отправка будет обрабатываться Actor1.

Я использовал следующий подход для изменения блокирующего вызова

Map<Int, Int> foo() {
     CompletionStage<List<String>> finalList = foo_2();
     finalList.whenComplete(
        // what to do here? 
     )
     // Map<Int, Int> finalMap = // do stuff with finalList to get Map<Int, Int>;

     return finalMap;
}

CompletionStage<List<String>> foo_2() {
    
     CompletionStage<List<String>> Querylist = ask(Actor2)
     
     
     return QueryList;
}

Я не уверен, как правильно использовать конструкцию CompletionStage, чтобы получить тот же результат, который я получал при вызове блокировки futures.get ().

2

Лучший ответ

1

Если вы используете типизированный Akka (подразумевается из тега), вам вообще не понадобится будущее или адаптер сообщений. Просто используйте ActorContext.ask.

Смотрите документацию для запроса-ответа с запросом между двумя участниками.

В широком смысле, вы бы избавились от foo и foo_2 методы, переместите адаптер сообщений, который вы настроили, в ActorContext.ask позвоните и замените экземпляры, в которые вы звонили ранее foo с призывом к ActorContext.ask. Если ответ, который ваш актер отправляет на сообщение, приведшее к запросу, зависит от ответа на запрос, то хорошей практикой является встраивание требуемых частей состояния в сообщение, которое генерирует адаптер.

2021-10-25 00:19:07

Спасибо за ваш ответ, вот чем я в итоге занялся. Знаете ли вы, в чем разница между выполнением .tell() и использованием ActorContext.ask()? Есть ли разница в том, что вы явно передаете "обработчик" в ActorContext.ask() ?
PyWalker2797

В конечном счете, ask выполняет всю работу по управлению взаимодействием запроса и ответа за вас: он построен поверх подсказок (в конце концов, более или менее все в Akka есть). В широком смысле, ask порождает субъекта и вводит ссылку на этого субъекта в качестве адреса для ответа в отправляемом сообщении. Когда этот субъект получает сообщение, он выполняет адаптер и пересылает адаптированный ответ субъекту, отправившему запрос; этот субъект также планирует сообщение для себя после истечения времени ожидания, которое он преобразует в сообщение о времени ожидания.
Levi Ramsey

Поскольку он порождает субъекта для получения ответа, он несколько менее эффективен, чем регистрация адаптера сообщений, выполнение запроса и планирование тайм-аута для себя. Однако у вас может быть произвольно много запросов с разными адаптерами в полете: с адаптером tell + вы можете превысить лимит одного адаптера для каждого типа (регистрация другого адаптера для одного и того же типа может быть непредсказуемой, и наследование также может привести к хаосу при таком подходе). Подход tell + адаптер имеет то преимущество, что позволяет получать несколько ответов.
Levi Ramsey

Это многое проясняет. Вы примерно знаете, насколько велики накладные расходы?
PyWalker2797

Не могли бы вы также помочь мне с другим вопросом.- stackoverflow.com/questions/69725512/...
PyWalker2797

Накладные расходы незначительны: потребление нескольких сотен байт памяти и, вероятно, дополнительная задержка в получении ответа на запрос в микросекунду или около того.
Levi Ramsey
1

Вы можете использовать pipeToSelf, смотри https://doc.akka.io/docs/akka/current/typed/interaction-patterns.html#send-future-result-to-self, чтобы отправить результат запроса самому актеру. Вместо того, чтобы пытаться получить ценность для finalList непосредственно в foo(), что возможно только при блокировке get, результат foo() может быть отправлен самому исполнителю, и в этом случае вы обрабатываете его, как любое другое сообщение. Для этого рекомендуется создать определенный тип сообщения.

Вам также следует взглянуть на CompletionStage методы, самое главное thenApply (https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletionStage.html#thenApply-java.util.function.Функция -), которая позволяет преобразовывать результаты, например, для создания Map из finalList, и, например, MapMessage из Map. Затем вы бы справились с MapMessage как и любое другое сообщение в актере.

2021-10-25 00:12:28

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

На других языках

Эта страница на других языках

Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................