Список установки нулевых значений с параллельным потоком - PullRequest
0 голосов
/ 17 октября 2018

У меня есть следующий код

final String arr[] = {"A", "B", "C", "D"};
final List<String> list1 = new ArrayList<>();
final List<String> list2 = Arrays.asList(arr).parallelStream()
                          .peek(s -> list1.add(s + s))
                          .map(s -> s + s)
                          .collect(Collectors.toList());
System.out.println(list1);
System.out.println(list2);

И я получаю следующий результат:

[null, AA, DD, null]
[AA, BB, CC, DD]

Почему некоторые элементы показывают null в списке1?Я знаю, что должен использовать SynchronizedList с parallelStream, но значения null меня удивляют.Как только вы добавляете что-то в список, этот слот должен быть установлен, и следующее выполнение должно было добавить к нему другое значение.

1 Ответ

0 голосов
/ 17 октября 2018

ArrayList является не потокобезопасной коллекцией, и вы пытаетесь обновить ее из многочисленных потоков с помощью parallelStream, что, как вы видите, является результатом resizing внутреннего массива этого ArrayList - эта операция также не является поточно-ориентированной, сначала вы увеличиваете массив и , затем перемещаете в него элементы: возможно, элементы не были перемещены, и вы пытаетесь получить к нему доступ.

Всделать это более явным, когда происходит изменение размера, создается массив новый с увеличенным размером - этот новый массив, если он заполнен null s только после копирования.

Это действительно непредсказуемо, что произойдет, просто не надейтесь ни на что из этого.

РЕДАКТИРОВАТЬ

Я не могу опубликовать это как комментарий,но вот код, подтверждающий, что null можно увидеть:

List<Integer> result = IntStream.iterate(0, i -> i + 1)
            .takeWhile(i -> {
                String arr[] = { "A", "B", "C", "D", "E", "F", "G", "H", "R", "T" };
                List<String> list = new ArrayList<>();
                Arrays.stream(arr)
                        .parallel()
                        .peek(list::add)
                        .forEach(x -> {
                        });

                if (list.contains(null)) {
                    System.out.println("It took " + i + " steps to see a null");
                    return false;
                }

                return true;
            })
            .boxed()
            .collect(Collectors.toList());
...