JDK8에서 parallelStream을 사용할 때 몇 개의 스레드가 생성됩니까? 예를 들어, 코드에서 :
list.parallelStream().forEach(/** Do Something */);
이 목록에 100000 개의 항목이있는 경우 몇 개의 스레드가 생성됩니까?
또한 각 스레드가 작업 할 동일한 수의 항목을 얻거나 무작위로 할당됩니까?
답변
오라클의 병렬 스트림 구현 [1]은 현재 스레드를 사용하며, 필요한 경우 ForkJoinPool.commonPool()
기본 크기가 CPU 코어 수보다 1보다 작은 기본 포크 조인 풀을 구성하는 스레드도 사용합니다. .
공용 풀의 기본 크기는 다음 속성을 사용하여 변경할 수 있습니다.
-Djava.util.concurrent.ForkJoinPool.common.parallelism=8
또는 자체 풀을 사용할 수 있습니다.
ForkJoinPool myPool = new ForkJoinPool(8);
myPool.submit(() ->
list.parallelStream().forEach(/* Do Something */);
).get();
순서와 관련하여 작업은 특정 순서없이 스레드를 사용할 수있는 즉시 실행됩니다.
@Holger가 올바르게 지적했듯이 이것은 구현 특정 세부 사항입니다 ( 문서 하단에 모호한 참조 가 하나 뿐 임), 두 접근 방식 모두 Oracle의 JVM에서 작동하지만 다른 공급 업체의 JVM에서 작동하는 것이 보장되지는 않습니다. Oracle 이외의 구현에는 존재하지 않으며 Streams ForkJoinPool
는 ForkJoinTask.fork
완전히 쓸모없는 행동을 기반으로 내부적으로 대안을 렌더링 할 수도 없습니다 (이에 대한 자세한 내용 은 여기 를 참조하십시오 ).
답변
@uraimo가 맞지만 대답은 정확히 “Do Something”이하는 일에 달려 있습니다. parallel.streams API는 몇 가지 흥미로운 문제가있는 CountedCompleter 클래스를 사용합니다. F / J 프레임 워크는 결과를 보관하기 위해 별도의 개체를 사용하지 않기 때문에 긴 체인은 OOME을 생성 할 수 있습니다. 또한 이러한 긴 체인은 때때로 스택 오버플로를 유발할 수 있습니다. 이러한 문제에 대한 답은 이 기사 에서 지적한대로 Paraquential 기법을 사용하는 것입니다 .
다른 문제는 중첩 된 병렬 forEach를 사용할 때 과도한 스레드 생성입니다.