Ответ 1
в зависимости от ситуации, вы не теряете все преимущества parallelism, используя ForEachOrdered
.
Предположим, что у нас есть что-то как таковое:
stringList.parallelStream().map(String::toUpperCase)
.forEachOrdered(System.out::println);
В этом случае мы можем гарантировать, что операция терминала ForEachOrdered
будет печатать строки в верхнем регистре в порядке встречи, но мы не должны предполагать, что элементы будут переданы промежуточной операции map
в том же порядке они были отобраны для обработки. Операция map
будет выполняться одновременно несколькими потоками. Таким образом, все еще может выиграть от parallelism, но это просто не использует весь потенциал parallelism. В заключение мы должны использовать ForEachOrdered
, когда необходимо выполнить действие в порядке вызова потока.
изменить следующий комментарий:
Что происходит, когда вы пропускаете операцию
map
? Меня больше интересуетForEachOrdered
сразу послеparallelStream()
если вы имеете в виду что-то вроде:
stringList.parallelStream().forEachOrdered(action);
нет никакой пользы в этом, и я сомневаюсь, что подумали дизайнеры, когда они решили создать метод. в этом случае было бы более целесообразно:
stringList.stream().forEach(action);
чтобы распространить на ваш вопрос "Зачем кому-то использовать forEachOrdered с параллельным потоком, если мы теряем parallelism", скажем, вы хотели выполнить действие над каждым элементом относительно порядка столкновений потоков; в таком случае вам понадобится использовать ForEachOrdered
, поскольку операция терминала forEach
не является детерминированной при параллельном использовании, поэтому существует одна версия для последовательных потоков и одна специально для параллельных потоков.