Вызов метода Async внутри цикла for

0

У меня есть модель:

package com.example.asyncmethod;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

@JsonIgnoreProperties(ignoreUnknown=true)
public class User {

  private String name;
  private String blog;

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public String getBlog() {
    return blog;
  }

  public void setBlog(String blog) {
    this.blog = blog;
  }

  @Override
  public String toString() {
    return "User [name=" + name + ", blog=" + blog + "]";
  }

}

вызов службы, как показано ниже

package com.example.asyncmethod;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.util.concurrent.CompletableFuture;

@Service
public class GitHubLookupService {

  private static final Logger logger = LoggerFactory.getLogger(GitHubLookupService.class);

  private final RestTemplate restTemplate;

  public GitHubLookupService(RestTemplateBuilder restTemplateBuilder) {
    this.restTemplate = restTemplateBuilder.build();
  }

  @Async
  public CompletableFuture<User> findUser(Integer user) throws InterruptedException {
    logger.info("Looking up " + user);
    String url = String.format("https://api.github.com/users/%s", user);
    User results = restTemplate.getForObject(url, User.class);
    
    Thread.sleep(1000L);
    return CompletableFuture.completedFuture(results);
  }

}

Класс асинхронного бегуна:

package com.example.asyncmethod;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

import java.util.concurrent.CompletableFuture;

@Component
public class AppRunner implements CommandLineRunner {

  private static final Logger logger = LoggerFactory.getLogger(AppRunner.class);

  private final GitHubLookupService gitHubLookupService;

  public AppRunner(GitHubLookupService gitHubLookupService) {
    this.gitHubLookupService = gitHubLookupService;
  }

  @Override
  public void run(String... args) throws Exception {
    // Start the clock
    long start = System.currentTimeMillis();

    // in real use case before the for loop I will have a database call to get the number of records and based on the size I need to call that many number of times.
for(int i=0; i <= 10; i++){
    CompletableFuture<User> page1 = gitHubLookupService.findUser(1);
   }

    // Wait until they are all done
    CompletableFuture.allOf(page1).join();

    // Print results, including elapsed time
    logger.info("Elapsed time: " + (System.currentTimeMillis() - start));
    logger.info("--> " + page1.get());

  }

}

Итак, в приведенном выше цикле for я мог бы вызвать findUser в соответствии с количеством записей, возвращаемых БД.

Также в будущем мне может потребоваться добавить еще несколько асинхронных вызовов, таких как findOrders, findInventory, findAccess и т. Д., Которые будут вызывать другие службы через http.

Учитывая, что асинхронный вызов может быть успешным для одной записи и терпеть неудачу для другой записи, как я могу подойти здесь, чтобы вызвать асинхронный вызов наилучшим образом?

0

Если вы хотите реализовать все преимущества асинхронных вызовов, я предлагаю избегать использования CompletableFuture.get () или CompletableFuture.join ().

Использование этих вызовов блокирует ваш основной поток до тех пор, пока не будут выполнены все задачи (как часть CompletableFuture.allOf ()).

Вместо этого вы можете использовать различные функции, которые предоставляются для запуска функции Lamba по завершении всех фьючерсов (также позволяет обрабатывать сбой в любом из фьючерсов).

Пожалуйста, обратитесь к документации Java для получения более подробной информации и проверьте, какой метод более удобен в вашей реализации:

https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html