Почему list.parallelStream (). ForEach () не обрабатывает все элементы списка в Java? - PullRequest
5 голосов
/ 06 февраля 2020

Следующий код не помещает все элементы в список назначения после завершения параллельного процесса. Есть ли какая-либо причина для этого?

public static void main(String[] args) {

    List<Integer> source =new ArrayList<>();
    List<Integer> destination = new ArrayList<>();
    IntStream.range(0, 10000).forEach(element ->{
        source.add(element);
    });

    //System.out.println(source.size());

    source.parallelStream().forEach(c->{
        destination.add(c);
    });

    System.out.println("Source Size:"+source.size());
    System.out.println("destination size:"+destination.size());
}

Вывод: Размер источника: 10000 Размер назначения: 4343

Ответы [ 3 ]

6 голосов
/ 06 февраля 2020

Поскольку ArrayList не является потокобезопасной коллекцией. Использование потокаобезопасной коллекции, такой как CopyOnWriteArrayList, сделает ее правильной, но не обязательно эффективной.

Использование Collector будет намного проще и правильнее. например,

source.parallelStream().collect(Collectors.toList())
2 голосов
/ 06 февраля 2020

Операция forEach параллельного потока добавляет элементы к несинхронизированному Collection (ArrayList) из нескольких потоков. Поэтому операция не является поточно-ориентированной и имеет неожиданные результаты.

Использование forEachOrdered() вместо forEach() обеспечит добавление всех элементов source List к destination *. 1011 *.

Однако, как уже упоминалось в другом ответе, использование collect(Collectors.toList()) является правильным способом получения вывода List из Stream.

0 голосов
/ 06 февраля 2020

Потому что вы должны использовать параллельную версию списка адресатов. У вас есть несколько вариантов на выбор, например:

CopyOnWriteArrayList<Integer> destination  = new CopyOnWriteArrayList<>();

Изменить этот список дорого, потому что он создает копию базового массива при каждой модификации, но быстро при чтении списка.

Collections.synchronizedList(destination);

Каждый метод синхронизирован, поэтому он будет потокобезопасным

...