使用阻塞API时在Java中进行异步编程

时间:2015-07-01 19:00:27

标签: java asynchronous futuretask

我正在开发一个使用某些阻止的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()的函数基本上由一个在结果可用时自动调用的回调来处理?

2 个答案:

答案 0 :(得分:3)

有几种选择。

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

答案 1 :(得分:0)

您有两个基本选择:

  • 定期汇总结果:

    bootstrap_cmds: - sudo easy_install pip - sudo easy_install mechanize - sudo easy_install boto - sudo easy_install BeautifulSoup4 API提供方法Future来检查Callable的计算结果是否准备就绪。这是非阻塞方法,返回布尔值,如果结果准备就为true,否则为false。

  • 订阅结果并在等待结果准备好的通知时执行有用的工作。有很多方法可以实现这一点,可能最简单的方法是使用isDone()

可以在异步编程中使用的一些其他有用的模式,虽然不是很清楚,但是Observer PatternActive object

活动对象的工作方式是客户端通过阻塞调用并发对象的服务。有一个计划机制可以按优先级处理这些结果,因为它们来自或无论其他标准。

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

Active object