You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
동시성 프로그래밍 측면에서 자바는 항상 앞서갔고,
Java8부터 parallel() 메서드만 한 번 호출하면 파이프라인을 병렬 실행할 수 있는 스트림을 지원했다.
이렇게, 동시성 프로그램을 자바로 작성하는 것이 쉬워지고 있지만, 이를 올바르고 빠르게 작성하는 일은
어려운 작업이다.
동시성 프로그래밍을 할때는 Safety(안정성), Liveness(응답 가능) 상태를 유지하기 위해 애써야 하는데,
스트림에서도 마찬가지이다.
parallel 예시)
publicstaticvoidmain(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
numbers.stream() // 순차 스트림 생성
.map(n -> n * n) // 각 숫자의 제곱 계산
.forEach(System.out::println); // 결과 출력
}
publicstaticvoidmain(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
numbers.parallelStream() // 병렬 스트림 생성
.map(n -> n * n) // 각 숫자의 제곱 계산
.forEach(System.out::println); // 결과 출력
}
// 9// 25// 16// 4// 1// 스트림의 각 요소가 병렬 처리되어, 결과 순서가 다를 수 있다.
Stream 병렬처리에서 성능 개선을 기대할 수 없는 경우
Stream.iterate
Stream.iterate(0, n -> n + 1)
.limit(10)
.parallel() // 이 경우 병렬 처리가 큰 도움이 되지 않음
.forEach(System.out::println);
이 전 요소에 의존적이기 때문에, 큰 도움이 되지 않는다.
limit
Stream.of(1, 2, 3, 4, 5)
.parallel() // 병렬 처리
.limit(3) // 이 경우 병렬 처리의 효과가 제한적일 수 있음
.forEach(System.out::println);
병렬처리의 오버헤드가 실제 작업량보다 클 수 있다.
이외
작업 단위가 너무 작은 경우
공유 자원에 대한 의존성이 높은 경우
입출력(IO) 집약적인 작업
병렬화로 인한 부하 불균형
스트림 연산의 복잡성
CPU 코어의 수
Stream 병렬 처리에 적합한 경우
집계연산 (min, max, count, sum ... )
이러한 연산들은 데이터 집합의 각 요소를 독립적으로 처리할 수 있으며, 각 부분의 결과를 결합하는 것이 비교적 간단하다.
조건 검사 연산 (anyMatch, allMathch ... )
anyMatch와 allMatch 같은 연산은 조건을 만족하는 요소를 찾는 즉시 처리를 중단할 수 있다. 병렬 처리에서 이는 더 빠른 결과 도출로 이어질 수 있다.
병렬 처리에 적합한 스트림 소스
스트림 API를 사용할 때 병렬 처리의 효과가 가장 좋은 소스는 데이터를 효율적으로 분할하고 빠르게 접근할 수 있는 구조를 가진 경우
배열 , ArrayList
배열을 사용하므로, 인덱스를 통한 빠른 무작위 접근이 가능하다.
데이터를 효과적으로 분할하여 병렬 처리를 수행하기 쉽다.
HashMap, HashSet
해시 테이블은 분할하기 쉽고, 각 버킷에 대한 처리를 병렬로 수행할 수 있다.
그러나, HashMap은 데이터의 순서가 정의되어 있지 않기 때문에 순서에 의존하는 연산에는 적합하지 않다.
ConcurrentHashMap
스레드 안전성을 보장하면서도, 데이터의 효율적인 병렬 처리가 가능하다.
내부적으로 세분화된 락을 사용하여 동시성을 높이고 있다.
숫자 범위 (int 범위, long 범위)
특정 숫자 범위는 균일하게 분할하기 쉽고, 각 범위에 대한 연산은 독립적으로 수행될 수 있다.
Spliterator
Spliterator는 Java 8에서 소개된 인터페이스로, '분할할 수 있는 반복자(Splittable Iterator)'의 약어.
이 인터페이스는 Iterable 요소들을 효율적으로 분할하여 병렬 처리를 지원하기 위해 설계되었다.
section: (7장 아이템 47, 48)
반환 타입으로는 스트림보다 컬렉션이 낫다
왜 컬렉션이 낫다고 하는가?
리스트 반환 예제
스트림 반환 예제
결과 - IllegalStateException 발생
스트림이 일회성 데이터 흐름이라는 것을 의미.
즉, 스트림은 데이터를 순회할 때 '한 번만 사용 가능한' 특성을 가진다.
따라서 여러번 반복하는 행위를 할 수 없는데,,
만약 사용자가 반복을 한다는 것을 미리 예견한다면
반복이라는 것을 명확히 할 수 있는 Iterable로 처리하는 것이 좋지만,
우리는 궁예가 아니기 때문에,
Collection으로 처리 해 주어서 사용자의 선택 폭을 넓혀주는 것이 최선일 것이다.
스트림 병렬화는 주의해서 사용해라
동시성 프로그래밍 측면에서 자바는 항상 앞서갔고,
Java8부터 parallel() 메서드만 한 번 호출하면 파이프라인을 병렬 실행할 수 있는 스트림을 지원했다.
이렇게, 동시성 프로그램을 자바로 작성하는 것이 쉬워지고 있지만, 이를 올바르고 빠르게 작성하는 일은
어려운 작업이다.
동시성 프로그래밍을 할때는 Safety(안정성), Liveness(응답 가능) 상태를 유지하기 위해 애써야 하는데,
스트림에서도 마찬가지이다.
parallel 예시)
Stream 병렬처리에서 성능 개선을 기대할 수 없는 경우
이 전 요소에 의존적이기 때문에, 큰 도움이 되지 않는다.
병렬처리의 오버헤드가 실제 작업량보다 클 수 있다.
Stream 병렬 처리에 적합한 경우
이러한 연산들은 데이터 집합의 각 요소를 독립적으로 처리할 수 있으며, 각 부분의 결과를 결합하는 것이 비교적 간단하다.
anyMatch와 allMatch 같은 연산은 조건을 만족하는 요소를 찾는 즉시 처리를 중단할 수 있다. 병렬 처리에서 이는 더 빠른 결과 도출로 이어질 수 있다.
스트림 API를 사용할 때 병렬 처리의 효과가 가장 좋은 소스는 데이터를 효율적으로 분할하고 빠르게 접근할 수 있는 구조를 가진 경우
배열을 사용하므로, 인덱스를 통한 빠른 무작위 접근이 가능하다.
데이터를 효과적으로 분할하여 병렬 처리를 수행하기 쉽다.
해시 테이블은 분할하기 쉽고, 각 버킷에 대한 처리를 병렬로 수행할 수 있다.
그러나, HashMap은 데이터의 순서가 정의되어 있지 않기 때문에 순서에 의존하는 연산에는 적합하지 않다.
스레드 안전성을 보장하면서도, 데이터의 효율적인 병렬 처리가 가능하다.
내부적으로 세분화된 락을 사용하여 동시성을 높이고 있다.
특정 숫자 범위는 균일하게 분할하기 쉽고, 각 범위에 대한 연산은 독립적으로 수행될 수 있다.
Spliterator
Spliterator는 Java 8에서 소개된 인터페이스로, '분할할 수 있는 반복자(Splittable Iterator)'의 약어.
이 인터페이스는 Iterable 요소들을 효율적으로 분할하여 병렬 처리를 지원하기 위해 설계되었다.
고효율 Spliterator 예제 구현
주요 포인트 설명
tryAdvance:
tryAdvance 메소드는 Spliterator의 현재 요소를 처리하고, 인덱스를 다음 요소로 이동한다.
trySplit:
trySplit 메소드는 Spliterator를 분할하는 데 사용된다. 이 메소드는 현재 Spliterator의 일부를 새로운 Spliterator로 분리하여 반환합니다. 이 방식은 병렬 처리에 매우 중요하다.
estimateSize:
현재 Spliterator에 남아있는 요소의 추정 개수를 반환한다.
characteristics:
Spliterator의 특성을 나타내는데, 이 예제에서는 ORDERED, SIZED, SUBSIZED, NONNULL, IMMUTABLE을 사용했다.
결론
스트림 병렬화는 오직 성능 최적화 수단임을 기억해야 한다.
다른 최적화와 마찬가지로 변경 전후로 반드시 성능을 테스트하여 가치있는지 확인해야한다.
reference
The text was updated successfully, but these errors were encountered: