csct3434
Introduction to Thread Pools in Java 본문
- 자바에서 쓰레드는 커널 쓰레드와 매핑된다
- 운영체제는 쓰레드를 대상으로 컨텍스트 스위칭을 수행한다
- 많은 쓰레드를 생성할수록 각 쓰레드의 작업 시간이 줄어들기 때문에, 자원(쓰레드)의 효율적인 관리가 필요하다
- 쓰레드 풀은 멀티 쓰레드 애플리케이션에서 자원을 절약하면서 병렬성을 유지하는데 도움이 된다
- 쓰레드 풀은 재사용 가능한 쓰레드를 제어하며 인자로 전달받은 Task를 실행하는 방식으로 동작한다.
[Thread Pools in Java]
1. Executor / ExecutorService
- Executor : Runnable 타입의 인스턴스를 인자로 받아 실행하는 submit 메서드를 제공하는 함수형 인터페이스
- ExecutorService
- submit 메서드 뿐만 아니라, task의 실행 흐름을 제어하는 다양한 메서드를 제공
- submit() : Executor와 달리, Runnable 뿐만 아니라 Callable 인스턴스도 지원
- 컴파일러는 반환값의 유무에 따라 람다식을 Runnable 혹은 Callable로 추론한다
- Runnable : 반환값 x / 예외 전달 x
- Callable : 반환값 o / 예외 전달 o
2. ThreadPoolExecutor
- 확장 가능한 쓰레드 풀 인스턴스로, 쓰레드 풀 튜닝에 사용되는 다양한 매개변수와 메서드를 제공
- 대표적인 매개변수 : corePoolSize, maximumPoolSize, keepAliveTime
- corePoolSize : 쓰레드풀에 기본적으로 유지되는 쓰레드(core thread)의 개수
- maximumPoolSize
- 코어 쓰레드가 모두 작업중이고 작업 큐가 full일 때 추가적인 쓰레드가 생성된다
- 이때, 코어 쓰레드와 추가 쓰레드를 합쳐서 생성할 수 있는 최대 쓰레드의 개수가 maximumPoolSize이다.
- keepAliveTime
- 쓰레드가 종료될 때까지 허용할 최대 유휴 시간
- 기본적으로 keepAliveTime은 코어 쓰레드에는 적용되지 않지만, allowCoreThreadTimeOut(true) 메서드를 호출한다면 코어 쓰레드도 keepAliveTime 이상 유휴 시 제거된다
3. ScheduledThreadPoolExecutor
- ThreadPoolExecutor의 확장 클래스 / ScheduledExecutorService의 구현체
- schedule() : 최초 대기 시간 이후, 주어진 작업을 1번 실행한다
executor.schedule(() -> {
System.out.println("Hello World");
}, 500, TimeUnit.MILLISECONDS);
- scheduleAtFixedRate() : 최초 대기 시간 이후, 주어진 작업을 일정 시간마다 반복한다 (각 작업의 시작 시간 기준)
CountDownLatch lock = new CountDownLatch(3);
ScheduledExecutorService executor = Executors.newScheduledThreadPool(5);
ScheduledFuture<?> future = executor.scheduleAtFixedRate(() -> {
System.out.println("Hello World");
lock.countDown();
}, 500, 100, TimeUnit.MILLISECONDS);
lock.await(1000, TimeUnit.MILLISECONDS);
future.cancel(true);
- scheduleWithFixedDelay() : scheduleAtFixedRate()와 유사하지만, 각 작업의 종료 시간을 기준으로 반복된다
4. Executors
- 쓰레드 풀 인스턴스를 생성하는 데 사용되는 헬퍼 클래스
- newFixedThreadPool(size)
- corePoolSize = size / maximumPoolSize = size / keepAliveTime = 0
- 고정된 크기의 쓰레드 풀을 생성하는데 사용
- newCachedThreadPool()
- corePoolSize = 0 / maximumPoolSize = Integer.MAX_VALUE / keepAliveTime = 60s
- Task Queue Size : 0 (SynchronousQueue)
- 처리 시간이 짧은 다수의 작업을 실행하는데 적합한 모델
- newSingleThreadExecutor()
- corePoolSize = 1 / maximumPoolSize = 1 / keepAliveTime = 0
- 작업 큐의 크기 : 무한
- 이벤트 처리에 적합한 모델
- newScheduledThreadPool(size)
- corePoolSize = size / maximumPoolSize = Integer.MAX_VALUE / keepAliveTime = 0
- 주어진 크기의 ScheduledThreadPoolExecutor 인스턴스를 생성하는데 사용
5. ForkJoinPool
- Java 7에 도입된 Fork/Join Framework의 핵심 부분
- 많은 하위 태스크를 생성하는 재귀 알고리즘의 자원 고갈 문제점을 work-stealing 알고리즘을 통해 해결한 쓰레드 풀 모델
- https://www.baeldung.com/java-fork-join
참고한 글
https://www.baeldung.com/thread-pool-java-and-guava
'개발 일지' 카테고리의 다른 글
Amazon S3 트리거와 Lambda를 활용한 썸네일 이미지 생성 (2) - 코드 구현 (1) | 2024.04.20 |
---|---|
Amazon S3 트리거와 Lambda를 활용한 썸네일 이미지 생성 (1) - 인프라 구축 (1) | 2024.04.16 |
중앙 집중식 로깅 구현하기 (feat. Logback, CloudWatch Logs) (0) | 2024.03.30 |
Github Actions Secret 버그 (0) | 2024.03.27 |
첫 서비스 출시기 (feat. EC2 Auto Scaling, Aurora Serverless) (0) | 2024.03.22 |