我正在开发一个使用某些阻止的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()
的函数基本上由一个在结果可用时自动调用的回调来处理?
答案 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 Pattern
和Active object
。
活动对象的工作方式是客户端通过阻塞调用并发对象的服务。有一个计划机制可以按优先级处理这些结果,因为它们来自或无论其他标准。
在下面的示例中,有一个实现,其中客户端服务被包装到Runnable中,但您可以轻松地将其更改为将服务包装到Callable中,并将代理放在Client和Active对象之间以订阅来自可调用的结果。