paralleStream()Java 1.8 vs 11

问题描述 投票:0回答:3

请考虑以下代码:

public class StreamDemo {
    public static void main(String[] args) {
        StreamObject obj = new StreamObject();
        obj.setName("mystream");

        List<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5));

        list.parallelStream().forEach(l -> {
            obj.setId(l);
            System.out.println(obj + Thread.currentThread().getName());
        });
    }

    static public class StreamObject {
        private String name;
        private Integer id;

        // getters, setters, toString()
    }
}

当编译并使用Java 11运行时,它返回以下内容:

StreamObject{name='mystream', id=4}ForkJoinPool.commonPool-worker-23
StreamObject{name='mystream', id=4}main
StreamObject{name='mystream', id=4}ForkJoinPool.commonPool-worker-9
StreamObject{name='mystream', id=4}ForkJoinPool.commonPool-worker-5
StreamObject{name='mystream', id=4}ForkJoinPool.commonPool-worker-19

但是对于Java 1.8,它返回不同的结果:

StreamObject{name='mystream', id=3}main
StreamObject{name='mystream', id=5}ForkJoinPool.commonPool-worker-2
StreamObject{name='mystream', id=2}ForkJoinPool.commonPool-worker-9
StreamObject{name='mystream', id=1}ForkJoinPool.commonPool-worker-11
StreamObject{name='mystream', id=4}ForkJoinPool.commonPool-worker-4

为什么结果不同?

java stream
3个回答
1
投票

两个结果均与Java内存模型一致。

执行的一种可能的顺序是:

T1 calls setId
T1 prints
T2 calls setId
T2 prints
...
T5 calls setId
T5 prints

但是,因为您不做任何事情来确保自动进行设置和打印,所以还可以执行以下操作(与许多其他顺序一样:]]

T3 calls setId
T1 calls setId
T2 calls setId
T5 calls setId
T4 calls setId

T1 prints
T1 prints
...
T5 prints

所以,它们之所以不同,是因为规范不要求它们相同。和某些细微(或可能不太细微)的实现差异意味着它们以不同的方式执行。

但是,您说,实现上的区别是什么?

这不是您应该关心的事情(听起来不知所措,我真的不知道)。 您应该关心Java内存模型,因为它提供了有保证的属性。

0
投票

尝试看一下它是1.8 vs 9,但应该让您更多地了解流在1.8中的工作方式


0
投票

我想如果您不使用forEachOrdered方法,而是在流上使用forEach,则意味着无论您使用哪种JDK,每次您都应该接收不同的值。

© www.soinside.com 2019 - 2024. All rights reserved.