Получить результат завершенного будущего - PullRequest
0 голосов
/ 10 марта 2020

Я использую завершаемое будущее, которое будет возвращено из потока asyn c в приложении Springboot. Моя реализация ниже. Насколько я понимаю, новый поток должен быть запущен для каждого элемента в списке и должен обрабатываться параллельно. Я понимаю, что .get заблокирует выполнение, но, поскольку он работает параллельно, я не вижу каких-либо улучшений в производительности. Любые предложения ниже, пожалуйста, для улучшения производительности?

ServiceA. java

@Autowired
ServiceB serviceb;


public List<String> getNames(List<Item> items) {
List<CompletableFuture<String>> list = new ArrayList<>();
List<String> returnList = new ArrayList<>();
for( Item item: items) {
  CompletableFuture<String> getItemName = serviceb.doProcess(item);
  list.add(getItemName):
}

for( CompletableFuture name : list) {
 returnList.add(name.get());
}
return returnList;
}

ServiceB. java

Class ServiceB {
@Async
Public CompletableFuture<String> doProcess(Item item)
{
   //do process
}

Ответы [ 3 ]

1 голос
/ 10 марта 2020

Вы можете позвонить allOf , чтобы дождаться всех результатов. Это будет ожидать завершения всего CompletableFuture.

        List<String> returnList = new ArrayList<>(items.size());
        CompletableFuture<String>[] tasks = items.stream()
            .map(value-> serviceb.doProcess(value).thenApply(returnList::add))
            .toArray(CompletableFuture[]::new);
        // wait for all tasks to finish
        CompletableFuture.allOf(tasks).get(50, TimeUnit.SECONDS);
        // return the results
        return returnList;

Вторым решением будет использование реактивного подхода, такого как шаблон издатель / подписчик ( Spring WebFlux или JavaRx ) , Таким образом, в вашем приложении будет мало операций ожидания. Но это повлияет на архитектуру вашего приложения.

Один совет : Для создания CompletableFuture используйте конструктор с ExecutorService , чтобы сохранить контрольный номер потоки и имеют контроль над запущенными потоками или когда приложение закрывается.

0 голосов
/ 10 марта 2020

Вы можете использовать thenAccept для добавления элементов в список.

List<String> list = new CopyOnWriteArrayList<>();
CompletableFuture.allOf(
    Stream.of(items).map(
        i -> CompletableFuture.supplyAsync(i).thenAccept(list::add)
    ).toArray(CompletableFuture[]::new)
).get(10, SECONDS);

return list;
0 голосов
/ 10 марта 2020

Функция get () определенно не сработает, поскольку она заблокирует основной поток выполнения для извлечения результата из потоков asyn c. Лучшим вариантом было бы использовать методы обратного вызова (thenApply () et c) соответственно, чтобы основной поток продолжал свою работу.

...