
Stream → 컬렉션(Collection), 배열(Array) 같은 데이터 소스를 함수형 프로그래밍 방식으로 처리할 수 있게 해주는 API, 원본 데이터를 바꾸지 않고 새로운 결과를 만듦 (불변성)
함수형 프로그래밍 → 함수(메서드) 를 일급 객체처럼 다루면서, 상태 변경을 최소화하고, 데이터를 함수의 조합으로 처리하는 프로그래밍 패러다임

- 소스(Source): 배열, 컬렉션, 파일 → 스트림으로 변환
- 중간 연산(Intermediate): filter, map, sorted … (스트림 가공)
- 최종 연산(Terminal): collect, forEach, reduce … (결과 생성)
스트림은 데이터 소스 → 중간 가공(체이닝) → 최종 소비(결과 도출)

- 여러 사용자 요청(th1, th2, th3 …)
- 각 스레드(stack 영역에 쌓임)가
MemberService를 호출
- 공유 객체(MemberService)
- Heap 영역에 하나 생성
- 여러 스레드가 동시에 접근할 수 있음
- 따라서 스레드 안정성(Thread-safety) 문제가 발생할 수 있음
- static ConcurrentHashMap
MemberService 내부에서 공용 데이터 저장소 역할
- 모든 스레드가 같은
static 영역에 접근
- HashMap 대신 ConcurrentHashMap을 사용해야 여러 스레드가 동시에 읽고/쓰더라도 안전 (동기화 보장)
- parallelStream()
- 컬렉션 데이터를 cpu가 병렬로 처리
- 내부적으로 ForkJoinPool(공용 스레드풀)을 이용해 여러 개의 스레드(th4, th5, th6, th7, th8 …)를 분배
- 데이터 블록을 나눠서 병렬로 처리한 뒤 결과를 합침 (속도가 느리다)
Arrays.asList
- 배열을 리스트처럼 다룰 수 있게 변환해주는 메서드
- 하지만 만들어진 리스트는 고정 크기 (add/remove 불가)