同步多个异步请求

时间:2018-01-20 00:23:44

标签: java concurrency future

给定异步服务,应在完成时关闭。我想执行多个请求实例。当所有请求完成后,我想关闭该服务。我想知道实现这一目标的最佳途径是什么。因此,以下代码演示了问题但没有实际关闭服务

    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

实现这一目标的最佳方法是什么?第一,第二,第三,没有这些?

1 个答案:

答案 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