Reduce返回并行流的不可预测结果

gst*_*low 3 java parallel-processing reduce java-8 java-stream

我用java stream reduce编写了以下代码示例:

Person reducedPerson = Person.getPersons().stream()
                .parallel()  //will return surprising result
                .reduce(new Person(), (intermediateResult, p2) -> {
                            intermediateResult.setAge(intermediateResult.getAge() + p2.getAge());
                            return intermediateResult;
                        },
                        (ir1, ir2) -> {
                            ir1.setAge(ir1.getAge() + ir2.getAge());
                            return ir1;
                        });
        System.out.println(reducedPerson);
Run Code Online (Sandbox Code Playgroud)

模型:

public class Person {

    String name;

    Integer age;

    public Person() {
        age = 0;
        name = "default";
    }

    //...
    public Person(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    public static Collection<Person> getPersons() {
        List<Person> persons = new ArrayList<>();
        persons.add(new Person("Vasya", 12));
        persons.add(new Person("Petya", 32));
        persons.add(new Person("Serj", 10));
        persons.add(new Person("Onotole", 18));
        return persons;
    }
}
Run Code Online (Sandbox Code Playgroud)

每个代码示例执行返回不同的结果:

例如: Person{name='default', age=256}

Person{name='default', age=248}
Run Code Online (Sandbox Code Playgroud)

我已经在里面找到了这个问题,combiner因为在后续流代码中正确执行了.

请帮助纠正组合器.

PS

预期结果:姓名为"默认"且年龄为72岁的人(列表中所有患者的总和)

PS

与Integer相同的代码,因为reduce结果可以正常工作:

Integer age = Person.getPersons().stream()
                .parallel()
                .reduce(0, (intermediateResult, p2) -> {
                    intermediateResult = intermediateResult + p2.getAge();
                    return intermediateResult;
                }, (ir1, ir2) -> {
                    System.out.println("combiner");
                    ir1 = ir1 + ir2;
                    return ir1;
                });
        System.out.println(age);
Run Code Online (Sandbox Code Playgroud)

Mis*_*sha 7

要执行可变缩减,请使用collect:

reducedPerson = Person.getPersons().parallelStream()
        .collect(
                Person::new,
                (p, q) -> p.setAge(p.getAge() + q.getAge()),
                (p, q) -> p.setAge(p.getAge() + q.getAge())
        );
Run Code Online (Sandbox Code Playgroud)

collect 专门设计用于即使并行安全地累积到可变容器中.