Java 平行流-多少是平行的?

Java 平行流-多少是平行的?,java,java-stream,Java,Java Stream,我有一个并行流,如下面我的Runner.java所示。但我意识到Runner类中的聚合方法是按顺序运行的。我想这是因为我有一个forEach,这个循环不能被打破,尽管我不确定。我对这种连续性的分析是基于我在下面的类的getter方法中打印的线程名称 虽然下面的代码有一个1000个对象的列表,但为了让较小的日志能够粘贴到这里,我将列表更改为10个项目以打印线程名称。日志位于Runner.java之后。查看它们,聚合方法总是由主线程执行,而不是由CommonPool执行。对于1000个项目也观察到了

我有一个并行流,如下面我的
Runner.java
所示。但我意识到Runner类中的聚合方法是按顺序运行的。我想这是因为我有一个
forEach
,这个循环不能被打破,尽管我不确定。我对这种连续性的分析是基于我在下面的类的getter方法中打印的线程名称

虽然下面的代码有一个1000个对象的列表,但为了让较小的日志能够粘贴到这里,我将列表更改为10个项目以打印线程名称。日志位于
Runner.java
之后。查看它们,聚合方法总是由主线程执行,而不是由
CommonPool
执行。对于1000个项目也观察到了相同的行为。如果forEach是导致顺序执行的原因,有人能帮我吗

Employee.java

public class Employee {
   private double salary;
   private String fName;
   private String lName;

   public Employee(double salary, String fName, String lName) {
      this.salary = salary;
      this.fName = fName;
      this.lName = lName;
   } 

   public Employee() {
   }

   public double getSalary() {
      return salary;
   }

   public void setSalary(double salary) {
     this.salary = salary;
   }

   public String getfName() {
      System.out.println("Thread.currentThread() + \"for getFname\" = " + Thread.currentThread() + 
     " for getFname");
      return fName;
   }

   public void setfName(String fName) {
      this.fName = fName;
   }

   public String getlName() {
       return lName;
   }

   public void setlName(String lName) {
       this.lName = lName;
   }

   @Override
   public String toString() {
       return "E{" +
            "s=" + salary +
            ", N='" + fName + '\'' +
            '}';
    }
  }
跑步者等级:

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class Runner {
    public static void main(String[] args) {
        ArrayList<Employee> list = new ArrayList<>();

        for (int i = 0; i < 1000; i++) {
            list.add(new Employee(i * 100, "A" + i, "Z" + i));

        }
        long l = System.currentTimeMillis();
        List<Employee> collect = list
                .parallelStream()
                .collect(Collectors.collectingAndThen(Collectors.groupingBy(Employee::getfName), Runner::aggregate));
        System.out.println("collect = " + collect.size());
        System.out.println(collect.stream().mapToDouble(e -> e.getSalary()).sum());
    }

    private static List<Employee> aggregate(Map<String, List<Employee>> t) {
        ArrayList<Employee> emps = new ArrayList<>();
        t.entrySet()
                .forEach(e -> {
                    System.out.println("Thread.currentThread() + \"within agrgate\" = " + Thread.currentThread() + "within agrgate");
                    Employee e1 = new Employee();
                    e.getValue().forEach(r -> {
                        e1.setSalary(e1.getSalary() + r.getSalary());
                        e1.setfName(r.getfName());
                    });
                    emps.add(e1);
                });
        return emps;
    }
}
该方法来自接口iterable,其中“按迭代顺序执行操作…”

然后,您可以为每个应用程序使用流

t.entrySet().parallelStream().forEach( e->{ 

更好的方法是让
groupingBy
收集器首先计算总和,而不是将其收集到列表中,然后执行另一种形式的缩减。
t.entrySet().parallelStream().forEach( e->{