如何在Java中发送异步请求并收集响应

时间:2017-05-11 10:00:48

标签: java asynchronous rx-java

我有一个允许说2000用户id的列表,我想将异步请求发送到同一个服务器,将id作为参数传递给WebTarget

系统将返回映射到UserReport类的JSON。它包含List<User>,大小为1(如果找到用户)。

对于每个结果,我想将用户保存在DataBase中。有没有办法让它全部异步?即只要我收到回复,就会向数据库发送一个INSERT。

我发送单个请求的代码:

public UserReport runRequest(String id){
    return this.webTarget.path("some_path")
            .queryParam("id", id)
            .request(MediaType.TEXT_PLAIN_TYPE)
            .get(new GenericType<UserReport >() {});
}

最后一个问题..使用Observable还是Future?

2 个答案:

答案 0 :(得分:0)

首先,大小为0或1的List<User>可以更改为Optional<User>

您可以使用flatMap来调度异步任务。这是我的代码。

public class Q43912265 {

  static Random random = new Random();

  public static void main(String[] args) {
    Observable.range(1, 1000)
        .map(String::valueOf)
        .flatMap(id ->
            Observable.just(id)
                .observeOn(Schedulers.io())
                .map(Q43912265::runRequest))
        .filter(ur -> ur.getUser().isPresent())
        .doOnNext(Q43912265::insert)
        .subscribe();
  }

  @SneakyThrows(InterruptedException.class)
  static UserReport runRequest(String id) {
    System.out.printf("request %s on %s\n", id, Thread.currentThread());
    Thread.sleep(random.nextInt(1000));
    System.out.printf("done %s on %s\n", id, Thread.currentThread());
    return new UserReport(id, Optional.ofNullable(random.nextDouble() > 0.7 ? null : new User(random.nextInt())));
  }

  static void insert(UserReport ur) {
    System.err.printf("insert %s on %s\n", ur, Thread.currentThread());
  }
}

@Value
class UserReport {
  String id;
  Optional<User> user;
}

@Value
class User {
  int id;
}

请注意,如果您直接运行上面的代码,它将在所有任务完成之前终止。使其阻止。

在这种情况下,您可以使用有限的线程更改调度程序,或io调度程序将创建大约1000个线程。

答案 1 :(得分:0)

我终于使用ExecutorServiceFuture

解决了这个问题

我发布了答案:

public List<User> getAllUsers(List<String> ids) {

    List<Future<UserReport>> futures = new ArrayList<>();
    ExecutorService executor = Executors.newFixedThreadPool(10);

    int counterU = 0;
    for (String id : ids) {
        Callable<UserReport> task = () -> {
            return runRequest(id);
        };
        futures.add(executor.submit(task));
        LOGGER.info("Added Task {} for UserId {}.", counterH++, id);
    }

    List<User> toReturn = new ArrayList<>();

    for (Future<UserReport> future : futures) {
        try {
            UserReport report = future.get();

            if (report.getUsers() != null) {
                User temp = report.getUsers().get(0);
                LOGGER.info("Got details for User {}.", temp.getId());
                toReturn.add(temp);
                insertUserToDB(temp);
            }

        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (ExecutionException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    executor.shutdown();
    return toReturn;
}