자바 병렬 스트림
서론
병렬 처리란 CPU의 멀티 코어를 활용, 작업의 요소를 분할해서 각각의 코어가 처리하는 것을 말한다. Java 8부터 Stream API가 도입되었고, 해당 기능을 이용해 손쉽게 병렬 처리를 구현 가능하다. 병렬 처리가 더 많은 코어를 활용하기 때문에 항상 빠르다고 생각할 수도 있으나 그렇지는 않다.
병럴성
데이터 병렬성
데이터를 분할해서 여러 데이터셋을 만들고 해당 데이터를 병렬 처리한다. 자바의 병렬 스트림이 이에 해당된다.
작업 병렬성
서로 다른 작업을 병렬 처리하는것을 말한다. 대표적인 예로는 톰캣과 같은 WAS가 있으며, 클라이언트가 요청을 보내면 개별 스레드로 작업을 병렬적으로 처리한다.
작업 방식
포크조인 프레임워크
병렬 스트림은 요소 처리를 위해 FORK 단계에서 내부적으로 데이터를 적당한 크기로 분할 후 연산 과정을 거친다.
JOIN 단계에서는 연산의 결과들을 조합해서 최종적인 결과물을 산출해낸다. 포크조인 프레임워크는 ExecutorService의 구현 객체인 ForkJoinPool을 사용해서 작업하는 스레드를 관리한다.
고려할 사항들
요소의 수와 요소당 처리 시간
만약 처리할 요소가 작거나 요소당 필요한 연산량이 작다면 일반 스트림 사용을 고려해 보아야 한다.
병렬 처리는 작업을 분할하고 다시 합치는 포크조인 단계가 있고, 스레드풀을 생성해야 하기 때문에 병렬 스트림 사용시 오히려 잦은 컨텍스트 스위칭과 이로 인한 오버헤드로 퍼포먼스가 저하될 수 있다.
스트림 소스의 종류
배열을 사용하거나 ArrayList 같은 경우는 인덱스로 내부 데이터에 순차적인 접근이 가능하기 때문에 요소를 쉽게 분리할 수 있으나, LinkedList처럼 다음 노드를 타고 가야 탐색이 되는 구조이거나 Map과 같이 순차적인 자료 구조가 아닐 경우 요소 분리가 쉽지 않기 때문에 속도가 저하될 수 있다.
코어의 수
증가한 스레드를 원할하게 처리할 만큼 CPU 코어의 숫자가 많지 않을 경우는 일반 스트림 사용을 고려해 보아야 한다.
참고
- 한빛미디어, [자바 기초 강의] 171강. 17.13 요소 병렬 처리, https://www.youtube.com/watch?v=X2y_BL1TNPI
- Baeldung, When to Use a Parallel Stream in Java, https://www.baeldung.com/java-when-to-use-parallel-stream