简体   繁体   English

为什么该流不能并行运行?

[英]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));
    }

}

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. 为每个元素设置一个id,并在打印消息时使用它。 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 ... 时间在forEach之后打印

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. 我认为它可能看起来是顺序的,因为run()方法完成得如此之快,以至于流没有时间创建所有线程。

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. 如果希望看到流实际上是并行运行的,请尝试在run()方法的循环内添加一个小的Thread.sleep(10)调用。

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. 即使流是并行的,它仍然会阻塞。

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 实现Runnable接口
  2. use new Thread(new Parallels()) to create the Threads 使用new Thread(new Parallels())创建线程
  3. use t.start() to start their Execution 使用t.start()开始执行
  4. use t.join() to wait for the Thread until it has finished 使用t.join()等待线程完成
  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 如果看不到任何并发,请插入Thread.sleep() ,这会减慢线程速度并“促使” VM切换到另一个线程

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM