Встречаются ли при выполнении промежуточных операций порядок, когда операция терминала, используемая в том же потоковом конвейере, не достигает порядка? - PullRequest
2 голосов
/ 14 апреля 2019

Если я использую операцию отображения в поточном конвейере с терминальной операцией forEach () (которая не учитывает порядок встречи, независимо от того, является ли этот поток последовательным или параллельным) в списке (как источник), карта будет соответствовать порядку встречи списка в случае последовательного или параллельного потока?

List<Integer> = Arrays.asList(1,2,3,4,5)
someList.stream().map(i -> i*2).forEach(System.out::println) // this is sequential stream
someList.parallelStream().map(i -> i*2).forEach(System.out::println) // this is parallel stream

Если да, то в этом посте https://stackoverflow.com/a/47337690/5527839, упомянутое действие карты будет выполняться параллельно. Если порядок поддерживается, то как он улучшит производительность при использовании параллельного потока. Какой смысл использовать параллельный поток?

Ответы [ 2 ]

2 голосов
/ 14 апреля 2019

Если порядок поддерживается, как он будет улучшать производительность при использовании параллельного потока. Какой смысл использовать параллельный поток? (да, все равно вы получите производительность, но не ожидаемый уровень)

Даже если вы используете forEachOrdered(), тогда как parallelStream, промежуточная операция map будет выполняться параллельными потоками, но в терминальной операции orEachOrdered заставляет их обрабатывать по порядку. Попробуйте код ниже, вы увидите параллельность в map операции

List<Integer> someList = Arrays.asList(1,2,3,4,5);
            someList.stream().map(i -> {
                System.out.println(Thread.currentThread().getName()+" Normal Stream : "+i);
                return i*2;
            }).forEach(System.out::println); // this is sequential stream

            System.out.println("this is parallel stream");

            someList.parallelStream().map(i -> {
                System.out.println(Thread.currentThread().getName()+" Parallel Stream : "+i);
                return i*2;
            }).forEachOrdered(System.out::println); // this is parallel stream

будет ли на карте порядок чести? Связан ли порядок заказов с промежуточными операциями?

Если это parallelstream, карта не будет встречаться в каком-либо порядке, если это нормальный поток, то карта будет встречаться по порядку, она полностью зависит от потока, а не от промежуточной операции

1 голос
/ 14 апреля 2019

В то время как многие промежуточные операции сохраняют порядок без необходимости явно указывать это желание, я всегда предпочитаю предполагать, что данные, проходящие через поток Java, не гарантируют, что в каждом сценарии заказы не будут упорядочены даже при одинаковом коде.

Когда порядок элементов должен быть сохранен, достаточно указать операцию терминала как упорядоченную операцию, и данные будут в порядке, когда она выйдет.Я полагаю, что в вашем случае вы будете искать

.forEachOrdered()

Если порядок будет сохранен, то как он улучшит производительность при использовании параллельного потока.Какой смысл использовать параллельный поток?

Я слышал много мнений по этому поводу.Я полагаю, что вы должны использовать параллельные потоки, только если вы выполняете нетривиальный объем обработки внутри конвейера, в противном случае накладные расходы на управление параллельным потоком в большинстве случаев ухудшат производительность по сравнению с последовательными потоками.Если вы выполняете некоторую интенсивную обработку, параллель все равно будет работать быстрее, чем последовательная, даже когда будет дано указание сохранить порядок, потому что, в конце концов, обрабатываемые данные хранятся в куче в любом случае, а указатели на эти данные - это то, что упорядочивается ивышел из конца трубы.Все, что нужно сделать потоку для упорядочения, это передать указатели в том же порядке, в котором они встречались, но он может работать с данными параллельно и просто ждать, пока данные в начале очереди еще не завершены.

Я уверен, что это немного упрощает, так как есть случаи, когда упорядоченный поток потребует, чтобы данные передавались из одного элемента в другой (например, сборщики). Но базовая концепция верна, так как даже в этомслучай, когда параллельный поток способен обрабатывать как минимум два фрагмента данных одновременно.

...