Можем ли мы улучшить производительность в списках, отличных от параллельных потоков Java 8 - PullRequest
0 голосов
/ 23 марта 2019

Я должен вывести данные откуда-то, вызвав rest API, который возвращает List.

  1. Сначала я должен получить объект List из одного API-интерфейса rest. Теперь используется параллельный поток и проходит через каждый элемент с forEach.

  2. Теперь для каждого элемента я должен вызвать какой-то другой API, чтобы получить данные, которые снова возвращают список, и сохранить тот же список, вызвав другой API остальных.

  3. Это займет около 1 часа для 6000 записей шага 1.

Я попробовал, как показано ниже:

restApiMethodWhichReturns6000Records
    .parallelStream().forEach(id ->{
       anotherMethodWhichgetsSomeDataAndPostsToOtherRestCall(id);
                       });


public void anotherMethodWhichgetsSomeDataAndPostsToOtherRestCall(String id) {

     sestApiToPostData(url,methodThatGetsListOfData(id));
}

Ответы [ 2 ]

2 голосов
/ 23 марта 2019

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

Хорошее обсуждение этого stackoverflow . Здесь вы видите некоторые хитрости для назначения конкретной задачи ForkJoinPool.

Прежде всего убедитесь, что ваша служба REST не блокируется.

Еще одна вещь, которую вы можете сделать, это поиграть с размером пула, поставив -Djava.util.concurrent.ForkJoinPool.common.parallelism=4 для JVM.

0 голосов
/ 26 апреля 2019

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

Я бы попробовал решение, используя CompletableFuture.

Код будет выглядеть примерно так:

List<CompletableFuture>> apiCallsFutures = restApiMethodWhichReturns6000Records
    .stream()
    .map(id -> CompletableFuture.supplyAsync(() -> getListOfData(id))    // Mapping the get list of data call to a Completable Future
                                 .thenApply(listOfData -> callAPItoPOSTData(url, listOfData))   // when the get list call is complete, the post call can be performed 
    .collect(Collectors.toList());

CompletableFuture[] completableFutures = apiCallsFutures.toArray(new CompletableFuture[apiCallsFutures.size()]); // CompletableFuture.allOf accepts only arrays :(

CompletableFuture<Void> all = CompletableFuture.allOf(completableFutures); // Combine all the futures

all.get(); // perform calls

Для получения более подробной информации о CompletableFutures, просмотрите: https://www.baeldung.com/java-completablefuture

...