给定异步服务,应在完成时关闭。我想执行多个请求实例。当所有请求完成后,我想关闭该服务。我想知道实现这一目标的最佳途径是什么。因此,以下代码演示了问题但没有实际关闭服务:
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);
}
}
我正在考虑关闭服务的不同选项:
以这种方式使用CountDownLatch:
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();
}
}
});
}
}
以这种方式使用CountDownLatch:
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();
}
与第一个选项类似,但使用AtomicInteger。
实现这一目标的最佳方法是什么?第一,第二,第三,没有这些?
答案 0 :(得分:2)
CountDownLatch
的第一个解决方案看起来不错,但还有其他方法。
从版本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());
您还可以使用具有类似方法CompletableFuture
的Java 8 allOf
类:
CompletableFuture.allOf(params.stream().map(svc::processRequest).toArray(CompletableFuture[]::new))
.thenAccept(v -> svc.close());
但在这种情况下,您必须让Service
返回CompletableFuture
。