4

I am working on a Java project that uses certain APIs that are blocking.

I would like to use asynchronous programming and callbacks, so that I don't have to block while waiting for the result. I've looked into using Java Future, but the only way I think I could use it is by calling the get() method which would block. I am open to using other ways to do asynchronous programming as well.

My current code looks like this.

Object res = blockingAPI();
sendToClient(res);

If I were to use Future, I would do it like this. But my understanding is get() is blocking.

private final int THREADS = Runtime.getRuntime().availableProcessors();
private ExecutorService executor = Executors.newFixedThreadPool(THREADS);

public void invokeApi() {
    Future<Object> future = executor.submit(new Callable<Object>() {
        public Object call() {
            return result;
        }
    });

    Object result = future.get(5, TimeUnit.SECONDS)
}

How could I go about implementing this such that the function of get() is basically handled by a callback that automatically gets invoked when the result is available?

RagHaven
  • 4,156
  • 21
  • 72
  • 113

2 Answers2

4

Several options.

One is to wrap your future into a CompletableFuture:

public static <T> CompletableFuture<T> makeCompletableFuture(Future<T> future) {
    return CompletableFuture.supplyAsync(() -> {
        try {
            return future.get();
        } catch (InterruptedException|ExecutionException e) {
            throw new RuntimeException(e);
        }
    });
}

An other one is to use Guava ListenableFuture:

ListeningExecutorService service = MoreExecutors.listeningDecorator(executor);
ListenableFuture<T> future = service.submit(callable);
Futures.addCallback(future, new FutureCallback<T>() {
    public void onSuccess(T t) {
        // ...
    }
    public void onFailure(Throwable thrown) {
        // ...
    }
});

You can also use Akka Futures which are highly composable.

Jean Logeart
  • 52,687
  • 11
  • 83
  • 118
0

You have two fundamental options :

  • periodically pool for result:

    Future API offers method isDone() to check if computation result of Callable is ready. This is non-blocking method which returns boolean value, true if result is ready, otherwise false.

  • subscribe to result and do useful work while waiting for notification that result is ready. There are many ways to achieve this and probably the most simple one would be to use Observer Pattern.

Some other useful patterns which could be used in asynchronous programming, albeit not so well know, are Active object and Half sync - half async.

Active object works in a way that clients invoke services of concurrent objects with blocking. There is a schedule mechanism which processes these result by priority, as they come or whichever other criteria.

In example bellow, there is an implementation where client services are wrapped into Runnable, but you could easily change it to wrap services into Callable instead, and put proxy between Client and Active object to subscribe on result from callable.

Active object

John
  • 5,189
  • 2
  • 38
  • 62