等待多个期货的回调

时间:2013-12-10 18:25:57

标签: java api concurrency future

最近我使用API​​深入研究了一些工作。 API使用Unirest http库来简化从Web接收的工作。当然,由于从API服务器调用数据,我试图通过使用API​​的异步调用来提高效率。我的想法结构如下:

  1. 通过返回期货结果
  2. 创建数据数组
  3. 显示数据+从数据中收集的其他信息
  4. 因此,在开始第二步之前,我需要返回所有数据。我的代码如下:

    Future < HttpResponse < JsonNode >  > future1 = Unirest.get("https://example.com/api").asJsonAsync(new Callback < JsonNode > () {
        public void failed(UnirestException e) {
            System.out.println("The request has failed");
        }
        public void completed(HttpResponse < JsonNode > response) {
            System.out.println(response.getBody().toString());
            responses.put(response);
        }
        public void cancelled() {
            System.out.println("The request has been cancelled");
        }
    });
    Future < HttpResponse < JsonNode >  > future2 = Unirest.get("https://example.com/api").asJsonAsync(new Callback < JsonNode > () {
        public void failed(UnirestException e) {
            System.out.println("The request has failed");
        }
        public void completed(HttpResponse < JsonNode > response) {
            System.out.println(response.getBody().toString());
            responses.put(response);
        }
        public void cancelled() {
            System.out.println("The request has been cancelled");
        }
    });
    doStuff(responses);
    

    我怎样才能这样做,只有在两个期货完成后才会调用doStuff?

1 个答案:

答案 0 :(得分:9)

有几个选择。您现在的代码从您发出请求的同一个线程中调用doStuff。如果要阻止两个请求都完成,则可以使用CountDownLatch。类似的东西:

CountDownLatch responseWaiter = new CountDownLatch(2);

Future <HttpResponse<JsonNode>> future1 = Unirest.get("https://example.com/api").asJsonAsync(new Callback<JsonNode>() {
  public void completed(HttpResponse<JsonNode> response) {
    responses.put(response);
    responseWaiter.countDown();
  }
  ...
});

// Similar code for the other get call
...

responseWaiter.await();
doStuff(responses);

如果您不希望在两个调用完成之前阻止该线程,则可以让每个匿名内部Callback类递增AtomicInteger。当计数为2时,您将调用doStuff。类似的东西:

AtomicInteger numCompleted = new AtomicInteger();

Future <HttpResponse<JsonNode>> future1 = Unirest.get("https://example.com/api").asJsonAsync(new Callback<JsonNode>() {
  public void completed(HttpResponse<JsonNode> response) {
    responses.put(response);
    int numDone = numCompleted.incrementAndGet();
    if (numDone == 2) {
      doStuff(responses);
    }
  }
});