Premise: I've already read this question and others, but I need some clarifications.
I understand that Stream.forEach method makes the difference (not only) when dealing with parallel streams, and this explains why this
//1
Stream.of("one ","two ","three ","four ","five ","six ")
.parallel()
.forEachOrdered(item -> System.out.print(item));
prints
one two three four five six
But when it comes to intermediate operations, the order is not guaranteed anymore when stream is parallelized. So this code
//2
Stream.of("one ","two ","three ","four ","five ","six ")
.parallel()
.peek(item -> System.out.print(item))
.forEachOrdered(item -> System.out.print(""));
will print something like
four six five one three two
Is it correct to say that forEachOrdered method only affects order of elements in its own execution? Intuitively, I'm thinking of //1 example being exactly the same as
//3
Stream.of("one ","two ","three ","four ","five ","six ")
.parallel()
.peek(item -> System.out.print("")) //or any other intermediate operation
.sequential()
.forEach(item -> System.out.print(item));
Is my intuition wrong? Am I missing something about the whole mechanism?
You are right in that the guarantees made for the action of forEachOrdered only apply to that action and nothing else. But it’s wrong to assume that this is the same as .sequential().forEach(…).
sequential will turn the entire stream pipeline into sequential mode, thus, the action passed to forEach will be executed by the same thread, but also the preceding peek’s action. For most intermediate operations, the exact placement of parallel or sequential is irrelevant and specifying both makes no sense as only the last one will be relevant.
Also, there is still no guaranty made about the ordering when using forEach, even if it hasn’t any consequences in the current implementation. This is discussed in “Does Stream.forEach respect the encounter order of sequential streams?”
The documentation of Stream.forEachOrdered states:
This operation processes the elements one at a time, in encounter order if one exists. Performing the action for one element happens-before performing the action for subsequent elements, but for any given element, the action may be performed in whatever thread the library chooses.
So the action may get invoked by different threads, as perceivable by Thread.currentThread() but not run concurrently.
Further, if the stream has an encounter order, it will get reconstituted at this place. This answer sheds some light one the difference of encounter order and processing order.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With