이 사이트의 실습은 자바스크립트를 켜야 움직입니다. 아래는 같은 내용을 글로 적은 것입니다.
공부 › Java › 스레드와 동시성
순차 호출과 병렬 호출
외부 호출 여러 개를 차례로 할까 한꺼번에 할까
상품 상세 화면 하나를 만들려고 여러 서비스를 호출합니다. 차례로 부르면 걸리는 시간이 모두 더해지고, 동시에 부르면 가장 느린 호출만큼만 걸립니다.
실행으로 대조 · JDK 21에서 실행해 확인
이 실습에 나오는 개념
- CompletableFuture
- 비동기 작업의 결과를 나타내는 객체로, 작업이 끝났을 때 이어서 실행할 동작을 연결하거나 여러 비동기 작업의 결과를 조합할 수 있다. 결과를 기다리며 스레드를 멈추지 않고 "끝나면 이것을 하라"는 식으로 흐름을 구성한다.
- 동기와 비동기
- 동기는 작업을 요청한 쪽이 결과를 받을 때까지 기다린 뒤 다음으로 진행하는 방식이다. 비동기는 작업을 요청해 두고 결과를 기다리지 않고 다음 일을 진행하며, 결과는 나중에 콜백이나 Future 등으로 전달받는 방식이다.
- 스레드 풀
- 스레드를 필요할 때마다 만들고 없애는 대신 일정 수의 스레드를 유지하며 재사용하는 구조다. 스레드 생성 비용을 줄이고, 동시에 실행되는 스레드 수를 제한해 과도한 메모리 사용과 컨텍스트 스위칭을 막는다. 처리할 작업은 큐에 쌓이고 빈 스레드가 가져가 실행한다. 톰캣의 요청 처리, DB 커넥션 풀도 같은 발상이다.
- ForkJoinPool과 공용 풀
- 큰 작업을 작은 작업으로 나눠 여러 스레드에서 처리하고 결과를 합치는 데 쓰는 스레드 풀이다. JVM에는 모두가 함께 쓰는 공용 풀(commonPool)이 있으며 병렬 스트림은 기본적으로 이 풀에서 실행된다. 여기서 오래 걸리는 작업을 실행하면 같은 풀을 쓰는 다른 작업까지 느려진다.
이렇게 바꿔 보세요
- 처음 설정으로 — 4개를 차례로 호출합니다. 시간이 전부 더해집니다.
- 병렬로 바꾸면 — 가장 느린 호출 하나의 시간만 걸립니다.
- 병렬인데 스레드가 2개뿐이면 — 동시에 2개까지만 진행됩니다.
- 느린 호출에 제한 시간 — 1초를 넘는 호출은 기다리지 않고 기본값으로 대신합니다.
- 5개를 순차로 — 호출이 하나 늘 때마다 그만큼 느려집니다.
처음 설정으로 실행하면
- 0.0초: 상품 정보 호출을 시작합니다(0.3초 걸리는 호출).
- 0.3초: 상품 정보 응답 도착.
- 0.3초: 재고 호출을 시작합니다(0.5초 걸리는 호출).
- 0.8초: 재고 응답 도착.
- 0.8초: 리뷰 호출을 시작합니다(0.8초 걸리는 호출).
- 1.6초: 리뷰 응답 도착.
- 1.6초: 추천 상품 호출을 시작합니다(1.6초 걸리는 호출).
- 3.2초: 추천 상품 응답 도착.
- 3.2초: 모든 결과가 모였습니다. 화면을 조립해 응답합니다.
실행 결과
- 순차 호출의 응답 시간은 모든 호출 시간의 합입니다. 서로 결과에 의존하지 않는 호출이라면 차례로 부를 이유가 없습니다.
코드
var product = productApi.get(id);
var stock = stockApi.get(id);
var reviews = reviewApi.list(id);
var recommend = recommendApi.list(id);
return new ProductPage(product, stock, reviews, recommend);
이 모형의 전제
각 호출의 소요 시간(상품 0.3초, 재고 0.5초, 리뷰 0.8초, 추천 1.6초, 쿠폰 0.4초)은 고정된 예시이고, 호출들은 서로의 결과가 필요 없다고 가정했습니다. 한 호출의 결과가 다음 호출의 입력이라면 그 둘은 순차로 해야 합니다. 병렬 호출은 스레드 하나가 호출 하나를 맡아 기다리는 블로킹 호출을 가정했습니다. completeOnTimeout은 JDK 9부터 있는 메서드입니다. 이 PC의 JDK 21에서 실제로 실행해 확인했습니다. 같은 시간의 호출 4개로 순차 3,243ms, 병렬(스레드 5개) 1,603ms, 병렬(스레드 2개) 2,127ms, 제한 시간 1초 적용 시 1,011ms가 나와 모형의 값(3.2초, 1.6초, 2.1초, 1.0초)과 일치했습니다.
앞 실습: 스레드 수와 컨텍스트 스위칭 · 다음 실습: 블로킹·논블로킹·가상 스레드