Эта реализация разбиения IntStream на самом деле не является поточно-ориентированной? - PullRequest
4 голосов
/ 16 апреля 2020

Этот "> ответ предоставляет реализацию для разбиения IntStream:

IntStream intStream = IntStream.iterate(0, i -> i + 1).limit(1000000);

Predicate<Integer> p = x -> r.nextBoolean();
Map<Boolean, List<Integer>> groups = intStream.collect(() -> {
    Map<Boolean, List<Integer>> map = new HashMap<>();
    map.put(false, new ArrayList<>());
    map.put(true, new ArrayList<>());
    return map;
}, (map, x) -> {
    boolean partition = p.test(x);
    List<Integer> list = map.get(partition);
    list.add(x);
}, (map1, map2) -> {
    map1.get(false).addAll(map2.get(false));
    map1.get(true).addAll(map2.get(true));
});

System.out.println(groups.get(false).size());
System.out.println(groups.get(true).size());

Но его редактирование упоминает, что эта реализация не является поточно-ориентированной. Однако, насколько я вижу, сборщик создает отдельный HashMap<List<Integer>> для каждого потока в параллельном потоке. Таким образом, каждая карта ограничена одним потоком. Функция разделения также ограничена одним потоком. Функция слияния объединяет результаты нескольких потоков, но, насколько мне известно, структура потоков гарантирует, что слияние будет выполнено потокобезопасным способом. Поэтому мой вопрос: действительно ли это решение не безопасно для потоков?

Кстати: ответ в любом случае дает более элегантное решение (Stream<Integer> stream = intStream.boxed(); et c), но я все еще хотел бы знать.

PS: Я хотел бы добавить этот вопрос в качестве комментария к исходному сообщению, но у меня даже нет репутации добавлять комментарии ...: |

Ответы [ 2 ]

4 голосов
/ 16 апреля 2020

Согласно документации Oracles

Как и Reduce (int, IntBinaryOperator), операции сбора могут быть распараллелены без дополнительной синхронизации.

https://docs.oracle.com/javase/8/docs/api/java/util/stream/IntStream.html#collect - java .util.function.Supplier- java .util.function.ObjIntConsumer- java .util.function.BiConsumer-

Так что, похоже, ваша интуиция права, что это так поточно-.

0 голосов
/ 16 апреля 2020

Ну, Random является поточно-ориентированным, но его не следует использовать таким образом, так как он имеет низкую производительность в условиях конкуренции, но ArrayList не является поточно-ориентированным. При параллельном потоке вы будете вызывать list.add(x) из нескольких потоков.

...