I have 1000 products which needs to executed in parallel and result of the output is also a collection. I need to maintain the order, so I used parallelStream()
with forEachOrdered
like below
products.parallelStream().forEachOrdered(pdt ->
finalProd.add(mapProduct(pdt)));
I have tested the code and it seems it is not efficient but better than using stream()
. As per the oracle documentation
the method forEachOrdered, which processes the elements of the stream in the order specified by its source, regardless of whether you executed the stream in serial or parallel. Note that you may lose the benefits of parallelism if you use operations like forEachOrdered with parallel streams.
we are not using full potential of parallelism if we use forEachOrdered
, Can someone suggest a better way to handle parallel task? I am worried about order only in last output, not concerned about order of execution
This assumes that finalProd
is supposed to have the products in products
mapped and in the same order:
finalProd = products
.parallelStream()
.map(p-> mapProduct(p))
.collect(Collectors.toList())
The parallelStream()
method creates a parallel stream to be processed concurrently, the map
operation maintains the order of the stream
and finally the collector collects them to a list which respects the order also.
You can check this claim in the stream
package javadoc:
Ordering
Streams may or may not have a defined encounter order. Whether or not a stream has an encounter order depends on the source and the intermediate operations. Certain stream sources (such as List or arrays) are intrinsically ordered, If a stream is ordered, most operations are constrained to operate on the elements in their encounter order; if the source of a stream is a List containing [1, 2, 3], then the result of executing map(x -> x*2) must be [2, 4, 6]...
...
For parallel streams, relaxing the ordering constraint can sometimes enable more efficient execution. Certain aggregate operations, such as filtering duplicates (distinct()) or grouped reductions (Collectors.groupingBy()) can be implemented more efficiently if ordering of elements is not relevant. Similarly, operations that are intrinsically tied to encounter order, such as limit(), may require buffering to ensure proper ordering, undermining the benefit of parallelism. In cases where the stream has an encounter order, but the user does not particularly care about that encounter order, explicitly de-ordering the stream with unordered() may improve parallel performance for some stateful or terminal operations. However, most stream pipelines, such as the "sum of weight of blocks" example above, still parallelize efficiently even under ordering constraints.
Emphasis is mine, but since we are only applying operations that respect the order, we can ensure the resulting order.