ycomp
ycomp

Reputation: 8573

Why can't this stream run in parallel?

How do I get this to run in parallel? my output is totally sequential and elapsed time is not displayed until everything is finished. This is my first attempt at parallelizing streams so I'm probably missing something obvious to everyone else. But I can't see what is wrong compared to sample code I looked at.

public class Paralells {


    void run() {
        for (int i = 1; i<=1000; i++) System.out.println(i);
    }


    public static void main(String[] args) {

        ArrayList<Paralells> a = new ArrayList();

        a.add(new Paralells());
        a.add(new Paralells());
        a.add(new Paralells());
        a.add(new Paralells());
        a.add(new Paralells());

        long x = System.currentTimeMillis();
        a.parallelStream().forEach(p -> p.run());
        System.out.println("ELAPSED: " + (System.currentTimeMillis()-x));
    }

}

Upvotes: 0

Views: 249

Answers (3)

Gerhard
Gerhard

Reputation: 118

import java.util.ArrayList;

public class Parallels implements Runnable {

    public void run() {
        for (int i = 1; i<=1000; i++) {
// uncomment this line, if you don't see concurrent execution
//            try { Thread.sleep(1); } catch (Exception e) {} 
            System.out.println(i);
    }   }


    public static void main(String[] args) {

        ArrayList<Thread> a = new ArrayList<>();

        for(int i=0; i<5; i++) a.add(new Thread(new Parallels()));

        long x = System.currentTimeMillis();

        for(Thread t : a) t.start();

        for(Thread t : a) try { 
            t.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("ELAPSED: " + (System.currentTimeMillis()-x));
    }
}
  1. implement the Runnable interface
  2. use new Thread(new Parallels()) to create the Threads
  3. use t.start() to start their Execution
  4. use t.join() to wait for the Thread until it has finished
  5. if you don't see any concurrency, insert a Thread.sleep() which slows down the Thread and "motivates" the VM to switch to another Thread

Upvotes: 0

marstran
marstran

Reputation: 28036

I tried your exact code, and it does execute in parallel. I think it may appear as sequential because the run() method finishes so fast that the stream hasn't had time to create all the threads.

If you want see that the stream is actually run in parallel, try adding a little Thread.sleep(10) call within your loop in the run() method.

Now, for the second part, the elapsed time will not be printed before everything is finished. Even though the stream is parallel, it will still be blocking.

Upvotes: 0

Jean-Baptiste Yun&#232;s
Jean-Baptiste Yun&#232;s

Reputation: 36401

But it is parallel! Experiment this:

import java.util.*;
public class Paralells {

    private int id;
    public Paralells(int id) { this.id = id; }
    void run() {
        for (int i = 1; i<=1000; i++) System.out.println(id+" "+i);
    }


    public static void main(String[] args) {

        ArrayList<Paralells> a = new ArrayList();

        a.add(new Paralells(1));
        a.add(new Paralells(2));
        a.add(new Paralells(3));
        a.add(new Paralells(4));
        a.add(new Paralells(5));

        long x = System.currentTimeMillis();
        a.parallelStream().forEach(p -> p.run());
        //a.forEach(p -> p.run()); // sequential
        System.out.println("ELAPSED: " + (System.currentTimeMillis()-x));
    }
}

An id is set for each element and is used while printing messages. You should be able to observe that the messages are interlaced. Compare with the sequential version (uncomment the appropriate line and comment the parallel version).

Of course, time is collected after everything finished. Time is printed after forEach...

Upvotes: 2

Related Questions