gpt4 book ai didi

java - 为什么使用parallelStream访问和修改Collection会得到不同的结果?

转载 作者:行者123 更新时间:2023-12-02 13:00:33 26 4
gpt4 key购买 nike

我对以下代码感到困惑

  public static void main(String[] args) throws InterruptedException
{
Integer[] intArray = {1, 2, 3, 4, 5, 6, 7, 8};
List<Integer> listOfIntegers =
new ArrayList<>(Arrays.asList(intArray));
List<Integer> parallelStorage = new ArrayList<>();//Collections.synchronizedList(new ArrayList<>());
listOfIntegers
.parallelStream()
// Don't do this! It uses a stateful lambda expression.
.map(e -> {
parallelStorage.add(e);
return e;
})
.forEachOrdered(e -> System.out.print(e + " "));
System.out.println();
parallelStorage
.stream()
.forEachOrdered(e -> System.out.print(e + " "));
System.out.println();
System.out.println("Sleep 5 sec");
TimeUnit.SECONDS.sleep(5);
parallelStorage
.stream()
.forEachOrdered(e -> System.out.print(e + " "));
}

每次执行它时我都会得到不同的结果,这真的让我很困惑,以下是一些结果:

Result 1:
1 2 3 4 5 6 7 8
null 3 8 7 1 4 5 6
Sleep 5 sec
null 3 8 7 1 4 5 6

Result 2:
1 2 3 4 5 6 7 8
6 2 4 1 5 7 8
Sleep 5 sec
6 2 4 1 5 7 8

这里有两个问题:

  • Q1:为什么parallelStorage的大小不确定?

    我理解使用fork/join框架的parallelStream,所以我猜问题是由一些没有完成工作的线程引起的,然后我暂停了主线程5秒,但似乎没有帮助,parallelStorage的大小仍然保持不变;

  • 问题2:为什么parallelStorage中存在空元素?

最佳答案

ArrayList 不是线程安全的。这意味着,如果您有两个线程同时更新列表,则这两个线程可能会以可能导致数据丢失的方式相互干扰(或者,对于某些数据结构,可能会完全破坏结构)。

我不知道添加到ArrayList时所采取的确切步骤顺序,但假设它是这样的。 ArrayList 应包含一个后备数组和一个指示当前大小的实例变量

  • 将数组大小读入局部变量N
  • 将新元素放入arr[N]
  • 将 1 添加到 N
  • N 存储回数组大小

现在假设您有两个线程执行此操作。由于没有同步,如果线程同时调用 add,则它们可以按此顺序执行步骤:

Read the array size into N
Read the array size into N
Put the new element in arr[N]
Put the new element in arr[N]
Add 1 to N
Add 1 to N
Store N into the array size
Store N into the array size

如果在任一线程调用 add 之前数组大小为 3,请注意,两个线程都会将 3 读入自己的局部变量 N;然后他们都会将新元素放在同一个位置,然后都将 4 存储到数组大小中。因此,即使“添加”了两个元素,新的数组大小也将是 4 而不是 5,并且新数据元素之一将丢失。

这就是您需要同步列表的原因。

(多个线程之间执行步骤的方式是不可预测的。因此,可以相信,在某些情况下,不同的执行顺序可能会导致两个线程在存储元素之前增加大小,从而导致元素在数组保持未使用状态,因此为 null。请不要将我在此处发布的步骤顺序视为 Java 运行时执行的实际步骤;这只是一个示例,我没有查看在 ArrayList 代码中。)

关于java - 为什么使用parallelStream访问和修改Collection会得到不同的结果?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44381516/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com