Я использую разделитель потоков непосредственно для операций низкого уровня в библиотеке, которую я пишу. Недавно я обнаружил очень странное поведение, когда я принимаю разделитель потока и чередую вызовы tryAdvance/trySplit
. Вот простой код, который демонстрирует проблему:Странное поведение Stream.spliterator для параллельных потоков
import java.util.Arrays;
import java.util.Spliterator;
public class SpliteratorBug {
public static void main(String[] args) {
Integer[][] input = { { 1 }, { 2, 3 }, { 4, 5, 6 }, { 7, 8 }, { 9 } };
Spliterator<Integer> spliterator = Arrays.stream(input).parallel()
.flatMap(Arrays::stream).spliterator();
spliterator.trySplit();
spliterator.tryAdvance(s -> {});
spliterator.trySplit();
spliterator.forEachRemaining(System.out::println);
}
}
Выход
5
6
9
Как вы можете видеть, после плоского картирования я должен получить заказанный поток последовательных чисел от 1
до 9
. Я разбил разделитель один раз, поэтому он должен перейти в какое-то промежуточное положение. Затем я использую элемент из него и разбиваю его еще раз. После этого я распечатываю все остальные элементы. Я ожидаю, что у меня будет несколько последовательных элементов из хвоста потока (возможно, нулевые элементы, это тоже будет хорошо). Однако я получаю 5
и 6
, затем внезапный прыжок до 9
.
Я знаю, что в настоящее время в разбрасывателях JDK не используются так: они всегда разделяются до обхода. Однако официальный documentation не запрещает прямое обращение к trySplit
после tryAdvance
.
Проблема не наблюдалась, когда я использую spliterator, созданный непосредственно из коллекции, массива, сгенерированного источника и т. Д. Это наблюдается только в том случае, если spliterator был создан из параллельного потока, который имел промежуточный flatMap
.
Итак, вопрос: я попал в ошибку или явным образом запретил где-то использовать spliterator таким образом?