2017-09-27 8 views
0

複数のデータベースクエリ(またはWebサービスリクエスト)を並行して送信し、後でそれらを集約したいとします。 stream APIまたはCompletableFutureを使用することをおすすめしますか?Stream APIまたはCompletableFutureを使用した並列dbクエリ?

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

FUTURES:

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

流れは確かに少ない冗長ですが、どちらがどのような理由のために好まれる必要がありますが?

Sidenote:この例をSQL = :firstname IN (..) and ... :lastname IN(..)で簡単にクエリできます。しかし、ストリームや先物を使うのは単なる例です。

タスクは、dbクエリではなく、複数のWebサービス要求を並列に送信することもできます。

+1

あなたはこれも読んでいますか?それはまったく動作しないかもしれません... https://stackoverflow.com/questions/44029856/using-jpa-objects-in-parallel-streams-with-spring – Eugene

+0

私は広いと意見に基づいて言うでしょう。メインビーフは同じです(並列実行されているもの)、サンプルコードでも両方の共通プールが使用されています。私はそれが主に他のコードが存在するかどうかに依存していると言いたい。 – Kayaman

+0

@Eugeneはもちろん、あなたがスレッドに 'EntityManager'をバインドしている時点に依存しています。この例では、リンクされた質問と同様の「スレッドクロス」は表示されません。 – Kayaman

答えて

1

あなたがすでに言ったように:「ストリームは確かにあまり冗長ではありません」、Streamを好んで使うのは十分ではありませんか?公平になるためには、Java 8ストリームAPIを使用して2番目のサンプルコードを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> result = requests.parallelStream() 
     .map(req -> query(req.getFirstname, req.getLastname)).collect(toList()); 

:並列ストリームにより、スレッド番号は固定ですForkJoinPool.commonPoolによって、CPUコア番号。通常、大量のWeb/dbリクエストを送信するには小さすぎます。たとえば、送信するウェブ/ dbリクエストが数十、数百になる場合、ほとんどの場合、ForkJoinPool.commonPoolで定義されたスレッド番号よりも20以上のスレッドでリクエストを送信する方がはるかに高速です。個人的には、並列ストリームでスレッド番号を指定する便利な方法がわかりません。あなたが参照できるいくつかの答えは次のとおりです:custom-thread-pool-in-java-8-parallel-stream

+0

だから私は結論づけることができると思います:いくつかの並列スレッドだけが必要な場合は 'streams'を使い、プールサイズを制御するために、より多くの並列度+に対してCompletableFutureを使用します。 – membersound

+0

そうです。パラレルストリームで提供されるスレッド番号で十分な場合結局のところ、パラレルストリームを使用しない理由はまったくありません。残念ながら、CompletableFuture:https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html#runAsync-java.lang.Runnable- ForkJoinPool.commonPool()も使用してください。あなたは私が投稿した質問で方法/答えを見つける必要があります。 –

関連する問題