Визуализация строки HTML с интерполированными компонентами React

Рассмотрим List stringList, который может быть напечатан многими способами с использованием конструкций Java 8:

stringList.forEach(System.out::println);                            // 1) Iterable.forEach
stringList.stream().forEach(System.out::println);                   // 2) Stream.forEach (order maintained generally but doc does not guarantee)
stringList.stream().forEachOrdered(System.out::println);            // 3) Stream.forEachOrdered (order maintained always)
stringList.parallelStream().forEach(System.out::println);           // 4) Parallel version of Stream.forEach (order not maintained)
stringList.parallelStream().forEachOrdered(System.out::println);    // 5) Parallel version ofStream.forEachOrdered (order maintained always)

Как эти подходы отличаются друг от друга?

Первый подход (Iterable.forEach). Итератор коллекции обычно используется и предназначен для fail-fast , что означает, что он выкинет ConcurrentModificationException, если базовая коллекция будет структурно изменена во время итерации. Как упоминалось в doc для ArrayList:

Структурная модификация - это любая операция, которая добавляет или удаляет один или несколько элементов или явно изменяет размер массива поддержки;

Таким образом, это означает, что для параметра ArrayList.forEach значение допустимо без каких-либо проблем. И в случае одновременного сбора, например. ConcurrentLinkedQueue итератор будет слабо согласованным , что означает, что действия, переданные в forEach, допускают внесение даже структурных изменений без исключения ConcurrentModificationException. Но здесь модификации могут быть или не быть видимыми в этой итерации.

Второй подход (Stream.forEach) - порядок не определен. Хотя это может не произойти для последовательных потоков, но спецификация не гарантирует этого. Кроме того, действие должно быть неинтерферирующим в природе. Как упоминалось в doc :

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

Третий подход (Stream.forEachOrdered) - действие будет выполняться в порядке обнаружения потока. Поэтому всякий раз, когда порядок имеет значение forEachOrdered, без второй мысли. Как упоминалось в doc :

Выполняет действие для каждого элемента этого потока в порядке выполнения потока, если поток имеет определенный порядок встреч.

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

Четвертый подход (Параллельный Stream.forEach). Как уже упоминалось, нет гарантии уважать порядок встреч, как ожидалось, в случае параллельных потоков. Возможно, что действие выполняется в разных потоках для разных элементов, которые никогда не могут иметь место с forEachOrdered.

Пятый подход (Параллельный Stream.forEachOrdered) - forEachOrdered будет обрабатывать элементы в порядок, заданный источником, независимо от того, является ли поток последовательным или параллельным. Поэтому нет смысла использовать это с параллельными потоками.

0
задан Dan 17 March 2019 в 22:51
поделиться