Java 同步多个异步请求
给定一个异步服务,该服务应在完成时关闭。我想执行一个请求的多个实例。当所有请求都完成时,我想关闭服务。我想知道实现这一目标的最佳方式是什么。下面的代码演示了问题,但没有实际关闭服务:Java 同步多个异步请求,java,concurrency,future,Java,Concurrency,Future,给定一个异步服务,该服务应在完成时关闭。我想执行一个请求的多个实例。当所有请求都完成时,我想关闭服务。我想知道实现这一目标的最佳方式是什么。下面的代码演示了问题,但没有实际关闭服务: class Service implements Closeable { public Service() {/*...*/} public ListenableFuture<Integer> processRequest(Integer param) {/*.
class Service implements Closeable {
public Service() {/*...*/}
public ListenableFuture<Integer> processRequest(Integer param) {/*...*/}
@Override
public void close() {/*...*/}
}
public void proccessRequests(ArrayList<Integer> params) {
Service svc = new Service();
for (Integer param : params) {
final ListenableFuture<Integer> res = svc.processRequest(param);
}
}
类服务实现可关闭{
公共服务(){/*…*/}
public ListenableFuture processRequest(整数参数){/*…*/}
@凌驾
公共void close(){/*…*/}
}
公共作废进程请求(ArrayList参数){
服务svc=新服务();
for(整数参数:参数){
最终ListenableFuture res=svc.processRequest(参数);
}
}
我正在考虑关闭该服务的不同选项:
- 这样做:
public void processRequests(ArrayList<Integer> params) { Service svc = new Service(); CountDownLatch latch = new CountDownLatch(params.size()); for (Integer param : params) { final ListenableFuture<Integer> res = svc.processRequest(param); Futures.addCallback(res, new FutureCallback<Integer>() { @Override public void onSuccess(Integer integer) { latch.countDown(); if (latch.getCount() == 0) { svc.close(); } } @Override public void onFailure(Throwable throwable) { latch.countDown(); if (latch.getCount() == 0) { svc.close(); } } }); } }
public void processRequests(ArrayList<Integer> params) { Service svc = new Service(); CountDownLatch latch = new CountDownLatch(params.size()); for (Integer param : params) { final ListenableFuture<Integer> res = svc.processRequest(param); Futures.addCallback(res, new FutureCallback<Integer>() { @Override public void onSuccess(Integer integer) { latch.countDown(); } @Override public void onFailure(Throwable throwable) { latch.countDown(); } }); } latch.await(); svc.close(); }
public void processRequests(ArrayList参数){ 服务svc=新服务(); CountDownLatch latch=新的CountDownLatch(params.size()); for(整数参数:参数){ 最终ListenableFuture res=svc.processRequest(参数); Futures.addCallback(res,newfuturecallback(){ @凌驾 成功时的公共void(整数){ 倒计时(); if(lock.getCount()==0){ svc.close(); } } @凌驾 失败时的公共无效(可丢弃){ 倒计时(); if(lock.getCount()==0){ svc.close(); } } }); } }
- 这样做:
public void processRequests(ArrayList<Integer> params) { Service svc = new Service(); CountDownLatch latch = new CountDownLatch(params.size()); for (Integer param : params) { final ListenableFuture<Integer> res = svc.processRequest(param); Futures.addCallback(res, new FutureCallback<Integer>() { @Override public void onSuccess(Integer integer) { latch.countDown(); if (latch.getCount() == 0) { svc.close(); } } @Override public void onFailure(Throwable throwable) { latch.countDown(); if (latch.getCount() == 0) { svc.close(); } } }); } }
public void processRequests(ArrayList<Integer> params) { Service svc = new Service(); CountDownLatch latch = new CountDownLatch(params.size()); for (Integer param : params) { final ListenableFuture<Integer> res = svc.processRequest(param); Futures.addCallback(res, new FutureCallback<Integer>() { @Override public void onSuccess(Integer integer) { latch.countDown(); } @Override public void onFailure(Throwable throwable) { latch.countDown(); } }); } latch.await(); svc.close(); }
public void processRequests(ArrayList参数){ 服务svc=新服务(); CountDownLatch latch=新的CountDownLatch(params.size()); for(整数参数:参数){ 最终ListenableFuture res=svc.processRequest(参数); Futures.addCallback(res,newfuturecallback(){ @凌驾 成功时的公共void(整数){ 倒计时(); } @凌驾 失败时的公共无效(可丢弃){ 倒计时(); } }); } satch.wait(); svc.close(); }
- 与第一个选项类似,但使用
实现这一目标的最佳方式是什么?第一,第二,第三,这些都没有?使用
倒计时闩锁
的第一个解决方案看起来不错,但还有一些其他方法
从20.0版开始,Futures类有一个完全为此目的而设计的whenAllComplete
方法。使用它,您可以编写:
Service svc = new Service();
Futures.whenAllComplete(params.stream().map(svc::processRequest).collect(Collectors.toList())).call(() -> {
svc.close();
return null;
}, ForkJoinPool.commonPool());
您还可以使用Java 8CompletableFuture
类,该类具有类似的方法allOf
:
CompletableFuture.allOf(params.stream().map(svc::processRequest).toArray(CompletableFuture[]::new))
.thenAccept(v -> svc.close());
但是在这种情况下,您必须使您的
服务
返回一个可完成的未来
我建议使用执行服务
。谢谢在第二个示例中,我是否应该调用get
或任何其他实例化函数来实际确保服务已关闭?@HannaKhalil然后在所有期货完成后立即调用accept
,因此您不必调用get
。但是如果您想让一些代码等待完成,当然可以添加.get()
。如果您担心某些期货可能会异常完成,您应该使用whenComplete
方法,而不是然后accept
:它将处理正常和异常情况。看看@HannaKhalil,如果有帮助,请接受答案