Java 使用流API或CompletableFuture的并行数据库查询?

Java 使用流API或CompletableFuture的并行数据库查询?,java,java-8,java-stream,Java,Java 8,Java Stream,假设我想并行发送多个数据库查询(或webservice请求),然后聚合它们。我最好使用流API还是CompletableFuture 流: List<Result> result = requests.parallelStream() .map(req -> query(req.getFirstname, req.getLastname)) .collect(

假设我想并行发送多个数据库查询(或webservice请求),然后聚合它们。我最好使用
API还是
CompletableFuture

流:

List<Result> result = requests.parallelStream()
                              .map(req -> query(req.getFirstname, req.getLastname))
                              .collect(toList());

//a database, or a webservice
private Result query(firstname, lastname);
List result=requests.parallelStream()
.map(req->query(req.getFirstname,req.getLastname))
.collect(toList());
//数据库或Web服务
私有结果查询(firstname,lastname);
未来:

List<CompletableFuture> futures;
for (QueryReq req: requests) { //given input
    futures.add(CompletableFuture
                        .supplyAsync(() -> query(req.getFirstname, req.getLastname));
}

//wait for all futures to complete and collect the results
List<Result> results = new ArrayList<>();
for (CompleteableFuture f : futures) {
   results.add(f.get());
}
上市期货;
对于(QueryReq:requests){//给定输入
futures.add(CompletableFuture)
.supplyAsync(()->查询(req.getFirstname,req.getLastname));
}
//等待所有期货交易完成并收集结果
列表结果=新建ArrayList();
for(完整的未来f:未来){
results.add(f.get());
}
虽然流肯定不那么冗长,但出于什么原因应该首选哪一个呢

旁注:我知道使用sql
=:firstname IN(..)和…:lastname IN(..)
可以更轻松地查询此示例。但这只是一个关于使用流还是未来的示例

任务还可以是并行发送多个webservice请求,而不是db查询。

正如您所说:“流肯定不会那么冗长”,您更喜欢使用
Stream
难道还不够吗?公平地说,我认为我们还应该使用Java 8流API的
CompletableFuture
重写第二个示例代码

List<Result> result = requests.stream()
        .map(req -> CompletableFuture.supplyAsync(() -> query(req.getFirstname, req.getLastname)))
        .collect(toList()).stream()
        .map(f -> f.get()).collect(toList());
List result=requests.stream()
.map(req->CompletableFuture.supplyAsync(()->查询(req.getFirstname,req.getLastname)))
.collect(toList()).stream()
.map(f->f.get()).collect(toList());
它看起来仍然非常冗长/比:

List<Result> result = requests.parallelStream()
        .map(req -> query(req.getFirstname, req.getLastname)).collect(toList());
List result=requests.parallelStream()
.map(req->query(req.getFirstname,req.getLastname)).collect(toList());

然而,我认为这里的关键点是如何设置并发线程数:通过并行流,线程数由CPU核心数固定。通常,这对于发送大量web/db请求来说太小了。例如,如果要发送数十个/数百个web/db请求,大多数情况下,使用20或m来发送请求要快得多比在
ForkJoinPool.commonPool
中定义的线程数更多的线程。我个人也不知道在并行流中指定线程数的方便方法。以下是一些答案,你可以参考:

你也能读一下吗?它可能根本不起作用……我想说的是广泛的和基于观点的。主要观点是一样的(事情是并行运行的),您的示例代码甚至使用了这两种代码的公共池。我认为这主要取决于其他代码的存在。@Eugene这当然取决于您在什么时候将
EntityManager
绑定到线程。给定的示例没有显示类似的“线程交叉”作为链接问题。查询是使用
spring
crudepository
运行的,而不是直接在实体管理器上运行。但这是一个不重要的细节,正如所写的那样,查询也可以是一个没有任何db访问的webservice调用。@Eugene链接问题与此无关。我不是像
那样运行代码>*.findAll().parallel()
,它在结果集上运行并行流。因此我认为可以得出结论:如果只需要几个并行线程,则使用
,如果需要更多并行线程,则使用
CompletableFuture
,以控制池大小。这是正确的。如果并行流中提供的线程数足够,则没有理由不使用不要使用并行流,毕竟它非常简单。不幸的是,CompletableFuture:也要使用ForkJoinPool.commonPool()。你需要在我发布的问题中找到方法/答案。