Taki ciekawy wątek się rozwinął jako off-topic w komentarzach: https://4programmers.net/Forum/1391030
No więc czy akumulator używany w Collector
albo w Stream.reduce()
musi być niemutowalny? Czy musi być thread-safe?
Ostatecznie zgodziliśmy się, że wystarczy, że będzie thread-safe, a najprostsza (a może i najszybsza) droga, prowadzi przez niemutowalność. Tylko uwaga, żeby nie zrobić sobie po drodze kwadratowej złożoności, np. tworząc kopię tablicy wyników.
(edit: Te przydługie i podejrzane wywody można pominąć i przejść od razu do mojego 3 postu, po drodze czytając JarkaR)
A co na to źródła? Potwierdzają:
Tomasz Nurkiewicz, Introduction to writing custom collectors in Java 8:
Generic type A simply defines the type of intermediate mutable data structure that we are going to use to accumulate items of type T in the meantime.
Czyli jest zgoda na mutowalność.
Na współbieżność bardzo musi uważać twórca implementujący interfejs Collector
. Od niego zależy, jakie wymagania będziemy stawiać akumulatorowi. Ogólne wymagania opisane są w javadocu do Collectora. Ale prościej jest użyć gotowego kolektora, który Java dostarcza nam w postaci funkcji Stream.reduce()
.
Czy korzystając ze świetnego kolektora Oracle'a, Stream.reduce()
, musimy mieć thread-safe accumulator? Nie znalazłem nigdzie bezpośredniej odpowiedzi, ale dokumentacja do reduce odsyła poprzez termin reduction, do dokumentacji pakietu java.util.stream. Tam wszystko (no, czy na pewno...) możemy doczytać.
Using reduce() instead removes all of the burden of parallelizing the reduction operation, and the library can provide an efficient parallel implementation with no additional synchronization required.
Czyli akumulator używany w Stream.reduce()
nie musi być thread-safe. Potwierdza to dokumentacja do reduce. Skoro nie wymagają tam tej cechy, to znaczy, że nie musimy jej wypełniać.
Intuicyjnie przeczuwałem, że tak będzie. Przecież nie ma powodu uruchamiać tego samego akumulatora jednocześnie. Na początek każdy wątek dostanie do swojej porcji danych nowy, pusty akumulator. Czyli jest bezpiecznie. W którymś momencie będziemy łaczyć te wyniki. Ale nadal nie widzę potrzeby, by jednocześnie używać tego samego akumulatora. Najpierw wątek "1" i "2" się połączy, gdzieś tam wątek "3" i "4", a potem połączy się to wszystko razem. No i gdzie miałby się tu akumulator wysypać?