4

我正在开发一个使用某些阻塞 API 的 Java 项目。

我想使用异步编程和回调,这样我就不必在等待结果时阻塞。我已经研究过使用 Java Future,但我认为我可以使用它的唯一方法是调用get()会阻塞的方法。我也愿意使用其他方式进行异步编程。

我当前的代码如下所示。

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

如果我要使用Future,我会这样做。但我的理解get()是阻塞。

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

我怎样才能实现这一点,以便函数get()基本上由回调处理,当结果可用时自动调用该回调?

4

2 回答 2

4

几个选项。

一种是将你的未来包装成一个 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);
        }
    });
}

另一种是使用 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) {
        // ...
    }
});

您还可以使用高度可组合的Akka Futures 。

于 2015-07-01T19:12:15.360 回答
0

您有两个基本选择:

  • 定期收集结果:

    FutureAPI 提供isDone()了检查 Callable 的计算结果是否准备好的方法。这是一个非阻塞方法,它返回布尔值,如果结果准备好,则返回 true,否则返回 false。

  • 订阅结果并在等待结果准备好的通知时做有用的工作。有很多方法可以实现这一点,最简单的一种可能是使用Observer Pattern.

可以在异步编程中使用的其他一些有用的模式,虽然不太为人所知,是Active objectand Half sync - half async

活动对象的工作方式是客户端通过阻塞调用并发对象的服务。有一种调度机制可以按优先级处理这些结果,当它们到来时或任何其他标准。

在下面的示例中,有一个将客户端服务包装到 Runnable 中的实现,但您可以轻松地将其更改为将服务包装到 Callable 中,并在 Client 和 Active 对象之间放置代理以订阅可调用的结果。

活动对象

于 2015-07-01T19:18:30.687 回答