Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/346.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 同步多个异步请求_Java_Concurrency_Future - Fatal编程技术网

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 8
CompletableFuture
类,该类具有类似的方法
allOf

CompletableFuture.allOf(params.stream().map(svc::processRequest).toArray(CompletableFuture[]::new))
    .thenAccept(v -> svc.close());

但是在这种情况下,您必须使您的
服务
返回一个
可完成的未来

我建议使用
执行服务
。谢谢在第二个示例中,我是否应该调用
get
或任何其他实例化函数来实际确保服务已关闭?@HannaKhalil
然后在所有期货完成后立即调用accept
,因此您不必调用
get
。但是如果您想让一些代码等待完成,当然可以添加
.get()
。如果您担心某些期货可能会异常完成,您应该使用
whenComplete
方法,而不是
然后accept
:它将处理正常和异常情况。看看@HannaKhalil,如果有帮助,请接受答案