私はJava 8でCompletionStage/CompletableFutureを使って非同期処理を行うために遊んでいます。これは非常にうまく機能します。ただし、ステージのイテレータ/ストリームの非同期処理を実行するステージが必要な場合がありますアイテム、これを行う方法がないようです。
具体的には、Stream.forEach()には、呼び出し後にすべてのアイテムが処理されるというセマンティクスがあります。私は同じことを望みますが、代わりにCompletionStageを使用します:
CompletionStage<Void> done = stream.forEach(...);
done.thenRun(...);
ストリームが非同期ストリーミングの結果によって裏付けられている場合、上記のコード自体でストリームが完了するのを待つよりもはるかに優れています。
これを現在のJava 8 APIでなんとかして構築することは可能ですか?回避策?
@KarolKrolが言及したように、CompletableFuture
のストリームでそれを行うことができます。
cyclops-react と呼ばれるCompletableFuture
のストリームでの作業を容易にするために、JDK8ストリームの上に構築するライブラリがあります。
ストリームを構成するには、cyclops-reactの流暢なpromise ike APIを使用するか、simple-reactの Stage
s を使用できます。
cyclops-react (このライブラリの作成者です)は、ストリームを処理するための StreamUtils クラスを提供します。それが提供する関数の1つはfutureOperationsです。これは、標準のStreamターミナル操作(および一部)にひねりを加えたアクセスを提供します。Streamは非同期で実行され、結果はCompletableFuture内に返されます。 。例えば
Stream<Integer> stream = Stream.of(1,2,3,4,5,6)
.map(i->i+2);
CompletableFuture<List<Integer>> asyncResult = StreamUtils.futureOperations(stream,
Executors.newFixedThreadPool(1))
.collect(Collectors.toList());
Streamをラップし、同じ機能を提供する便利なクラスReactiveSeqも、Nice Fluent APIで提供されています
CompletableFuture<List<Integer>> asyncResult = ReactiveSeq.of(1,2,3,4,5,6)
.map(i->i+2)
.futureOperations(
Executors.newFixedThreadPool(1))
.collect(Collectors.toList());
Adamが指摘したように cyclops-react FutureStreamsは、データを非同期に処理するように設計されています(FutureとStreamsを混合することにより)-I/Oのブロック(読み取りなど)を伴うマルチスレッド操作に特に適していますファイル、db呼び出し、残りの呼び出しなど)。
ストリームを作成し、各要素をCompletionStage
にマップし、CompletionStage.thenCombine()
を使用して結果を収集することは可能ですが、結果のコードは、このような単純なものを使用するよりも読みやすくはありません。
CompletionStage<Collection<Result>> collectionStage =
CompletableFuture.completedFuture(
new LinkedList<>()
);
for (Request request : requests) {
CompletionStage<Result> resultStage = performRequest(request);
collectionStage = collectionStage.thenCombine(
resultStage,
(collection, result) -> {
collection.add(result);
return collection;
}
);
}
return collectionStage;
この例は、読みやすさを失わない機能的なforEachに簡単に変換できます。ただし、ストリームのreduce
またはcollect
を使用するには、それほど細かくないコードを追加する必要があります。
更新:CompletableFuture.allOf
およびCompletableFuture.join
将来の結果のコレクションを将来の結果のコレクションに変換する、より読みやすい別の方法を提供します。