使用Stream API或CompletableFuture进行并行数据库查询?

时间:2017-09-27 10:57:51

标签: java java-8 java-stream

假设我想并行发送多个数据库查询(或Web服务请求),然后再聚合它们。我会更好地使用stream API或CompletableFuture吗?

STREAM:

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<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());
}

虽然stream肯定不那么冗长,但出于什么原因应该首选哪一个?

Sidenote :我知道我可以使用sql = :firstname IN (..) and ... :lastname IN(..)更轻松地查询此示例。但它只是一个关于使用流或期货的例子。

任务也可以是并行发送多个Web服务请求,而不是数据库查询。

1 个答案:

答案 0 :(得分:1)

正如您已经说过的那样:“流量肯定不那么冗长”,是不是更愿意为您使用create-react-app?公平地说,我认为我们也应该用Java 8 Stream API用Stream重写第二个示例代码。

CompletableFuture

它看起来仍然比以下更加冗长/更长:

List<Result> result = requests.stream()
        .map(req -> CompletableFuture.supplyAsync(() -> query(req.getFirstname, req.getLastname)))
        .collect(toList()).stream()
        .map(f -> f.get()).collect(toList());

但是,我认为这里的关键点是如何设置并发线程数:通过并行流,线程数由ForkJoinPool.commonPool固定,CPU核心数。通常,这对于发送大量Web / db请求来说太小了。例如,如果要发送数十/数百个web / db请求,则大多数情况下发送具有20个或更多线程的请求要比List<Result> result = requests.parallelStream() .map(req -> query(req.getFirstname, req.getLastname)).collect(toList()); 中定义的线程数快得多。就个人而言,我也不知道在并行流中指定线程号的方便方法。以下是您可以参考的一些答案:custom-thread-pool-in-java-8-parallel-stream