Java 8의 parallelStream에는 몇 개의 스레드가 생성됩니까?


83

JDK8에서 parallelStream을 사용할 때 몇 개의 스레드가 생성됩니까? 예를 들어, 코드에서 :

list.parallelStream().forEach(/** Do Something */);

이 목록에 100000 개의 항목이있는 경우 몇 개의 스레드가 생성됩니까?

또한 각 스레드가 작업 할 동일한 수의 항목을 얻거나 무작위로 할당됩니까?



@assylias 정말 좋은 대답입니다.
Umberto Raimondi

답변:


79

오라클의 병렬 스트림 구현 [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 ForkJoinPoolForkJoinTask.fork완전히 쓸모없는 행동을 기반으로 내부적으로 대안을 렌더링 할 수도 없습니다 (이에 대한 자세한 내용 은 여기참조하십시오 ).


5
작업 수가 충분히 적 으면 병렬 스트림이 실제로 주 스레드에서 실행될 수 있다는 점을 추가 할 가치가 있습니다.
assylias 2015-06-12

15
그것이 주목해야한다 StreamAPI를 사용하는 단계의 ForkJoinPool일 구현의 세부 사항이다. 따라서 두 솔루션 모두 Oracle의 현재 구현에서 작동하지만 모든 곳에서 작동한다고 보장 할 수는 없습니다.
Holger

4

@uraimo가 맞지만 대답은 정확히 "Do Something"이하는 일에 달려 있습니다. parallel.streams API는 몇 가지 흥미로운 문제가있는 CountedCompleter 클래스를 사용합니다. F / J 프레임 워크는 결과를 보관하기 위해 별도의 개체를 사용하지 않기 때문에 긴 체인은 OOME을 생성 할 수 있습니다. 또한 이러한 긴 체인은 때때로 스택 오버플로를 유발할 수 있습니다. 이러한 문제에 대한 답은 이 기사 에서 지적한대로 Paraquential 기법을 사용하는 것입니다 .

다른 문제는 중첩 된 병렬 forEach를 사용할 때 과도한 스레드 생성입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.