Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Waiting for callback for multiple futures

Recently I've delved into a little bit of work using an API. The API uses the Unirest http library to simplify the work of receiving from the web. Naturally, since the data is called from the API server, I tried to be efficient by using asynchronous calls to the API. My idea is structured as follows:

  1. Create array of data by returning the results of futures
  2. Display data + additional information gathered from the data

Therefore, I need to have all the data returned before I can start the second step. My code is as follows:

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);

How would I make it so doStuff is called only after both of the futures are finished?

like image 805
John Mace Avatar asked Dec 10 '13 18:12

John Mace


People also ask

How to wait for a future to complete Flutter?

wait<T> method Null safety Returns a future which will complete once all the provided futures have completed, either with their results, or with an error if any of the provided futures fail.

What is ListenableFuture?

A ListenableFuture represents the result of an asynchronous computation: a computation that may or may not have finished producing a result yet. It's a type of Future that allows you to register callbacks to be executed once the computation is complete, or if the computation is already complete, immediately.

What does future get do?

A Future interface provides methods to check if the computation is complete, to wait for its completion and to retrieve the results of the computation. The result is retrieved using Future's get() method when the computation has completed, and it blocks until it is completed.

What is a Java future?

In Java, Future is an interface that belongs to java. util. concurrent package. It is used to represent the result of an asynchronous computation. The interface provides the methods to check if the computation is completed or not, to wait for its completion, and to retrieve the result of the computation.


1 Answers

There are a few options. The code you have now calls doStuff from the same thread where you make your requests. If you want to block until both requests have completed you could use a CountDownLatch. Something like:

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);

If you don't want to block that thread until both calls are complete, you could have each of your anonymous inner Callback classes increment an AtomicInteger. When the count is 2 you'd call doStuff. Something like:

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);
    }
  }
});
like image 74
Oliver Dain Avatar answered Sep 28 '22 11:09

Oliver Dain