2

I got a requirement to run a collection using parallel stream and it is always running in sequence, here in the below example List is always running in sequence where as IntStream is running in parallel. could some please help me to understand the difference between running a parallel Stream on IntStream and parallel Stream on List<String>.

Also, can you help with the code snippet how to run List<String> in parallel similar to how IntStream is running parallel?

import java.util.List;
import java.util.stream.IntStream;

public class ParallelCollectionTest {

    public static void main(String[] args) {

        System.out.println("Parallel int stream testing.. ");
        IntStream range2 = IntStream.rangeClosed(1, 5);
        range2.parallel().peek(t -> {
            System.out.println("before");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).forEachOrdered(System.out::println);

        System.out.println("Parallel String collection testing.. ");
        List<String> list = List.of("a","b","c","d");
        list.stream().parallel().forEachOrdered(o ->
                {
                    System.out.println("before");
                    try {
                        Thread.sleep(10000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(o);
                });
    }

}

output of the above code is below.

Parallel int stream testing.. 
before
before
before
before
before
1
2
3
4
5
Parallel String collection testing.. 
before
a
before
b
before
c
before
d

Eran
  • 387,369
  • 54
  • 702
  • 768
Varma
  • 47
  • 4
  • So you're saying this code is taking about 51 seconds to complete, with 50 seconds being spent on the second part? – ernest_k Jun 29 '21 at 11:43
  • 1
    no, I mean to say that IntStream processed elements in parallel as you see "before" is printed for multiple elements and it wait for the give sleep time and then printed the elements(1,2,3,4,5), but in case of List of Strings it printed "before" and waited until the sleep time and then printed the element "a", and it repeated those steps for each element(b,c,d) in seq. – Varma Jun 29 '21 at 11:53

1 Answers1

3

The different behavior is not caused by the different streams (IntStream vs. Stream<String>).

The logic of your two stream pipelines is not the same.

In the IntStream snippet you are performing the sleep in the peek() call, which allows it to run in parallel for different elements, which is why that pipeline ends quickly.

In the Stream<String> snippet you are performing the sleep in the forEachOrdered, which means the sleep() for each element must be performed after the sleep() of the previous element ends. That's the behavior of forEachOrdered - This operation processes the elements one at a time, in encounterorder if one exists.

You can make the second snippet behave similar to the first if you add a peek() call to it:

System.out.println("Parallel String collection testing.. ");
List<String> list = List.of("a","b","c","d","e","f","g","h");
list.stream().parallel().peek(t -> {
    System.out.println("before");
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
})
.forEachOrdered(System.out::println);

Now it will produce:

Parallel String collection testing.. 
before
before
before
before
a
b
c
d
Eran
  • 387,369
  • 54
  • 702
  • 768