Thread Pool은 매번 요청이 올 때마다 스레드를 생성하고 수거하는 것이 아닌, 설정한 스레드 수만큼 미리 생성하여 사용하는 것을 말합니다.
- Thread Pool이 필요한 이유
- 새로운 스레드를 생성할 때마다 스레드를 위한 메모리 영역(스택)을 확보하고, 스레드가 더 이상 필요 없으면 해당 메모리 영역을 회수하는데, 이는 오버헤드가 큰 작업입니다.
Executors 클래스의 정적 메서드를 통해 ExecutorService의 구현 객체를 제공받아 스레드 풀을 생성할 수 있습니다.
먼저 ThreadPoolExecutor를 설명하기 위해, Thread Pool 종류 중 하나인 newFixedThreadPool() 메서드를 살펴보겠습니다.
내부에서 ThreadPoolExecutor 클래스 생성자를 호출하고 있는데요.
해당 클래스는 스레드 풀을 관리해 주는 클래스입니다.
- corePoollSize : 스레드 풀에서 스레드를 생성할 때 corePoollSize 수만큼 코어 스레드를 생성합니다.
- maximumPoolSize : 모든 위에서 지정한 코어 스레드가 모두 사용 중이고, 내부 큐도 가득 찼을 경우 커질 수 있는 스레드 풀의 최대 크기입니다.
- maximumPoolSize도 넘어가면 기본적으로 예외를 던진다.
- keepAliveTime : 현재 스레드 풀이 corePoolSize 보다 스레드가 많고, 초과한 스레드가 keepAliveTime 값보다 오랫동안 일하지 않으면 제거됩니다.
- unit : 시간 단위
- workQueue : corePoolSize가 가득 찼을 경우 스레드를 담아두는 대기 큐입니다.
Thread Pool 종류
1) Single Thread Executor
- 단일 스레드
- 단일 스레드가 실행 중 실패하거나 작업이 남은 경우 새로운 스레드를 생성합니다.
ExecutorService executorService = Executors.newSingleThreadExecutor();
2) Fixed Thread Executor
- 고정된 개수의 쓰레드를 생성하고, 모든 쓰레드가 작업 중이라면 Task Queue 에서 대기합니다.
- 실패 시 새로운 스레드를 생성합니다.
ExecutorService executorService = Executors.newFixedThreadPool(int nThreads);
3) Cached Thread Pool
- 필요한 경우 새로운 스레드를 생성하며, 이전에 생성했던 스레드가 존재한다면 이를 재사용합니다.
- 일반적으로 단기 비동기 작업을 많이 실행하는 프로그램에 좋습니다.
- 60초 동안 사용되지 않은 스레드는 종료되고 캐시에서 제거됩니다.
ExecutorService executorService = Executors.newCachedThreadPool();
4) Scheduler Thread Pool
- 설정한 Delay 이후에 실행하거나, 주기적으로 실행하도록 작업을 예약할 수 있습니다.
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(int corePoolSize);
스레드 풀에 작업 요청을 하는 방식은 execute( ), submit( ) 방식이 있습니다.
execute()
- 작업 처리 결과를 반환하지 않습니다.
- 작업 처리 도중 예외 발생하면 스레드가 종료되고 해당 스레드는 스레드풀에서 제거하고, 스레드풀은 작업 처리를 위해 새로운 스레드를 생성합니다.
submit()
- 작업 처리 결과를 반환합니다.
- 작업 처리 도중 예외가 발생하더라도 스레드는 종료되지 않고 다음 작업을 위해 재사용됩니다.
execute 테스트
실행 결과 작업 처리 도중 예외가 발생하면 새로운 스레드(스레드 이름이 모두 다른 것을 확인하실 수 있습니다.)를 생성하는 것을 확인할 수 있었습니다.
submit 테스트
작업 처리 도중 예외가 발생하더라도 스레드가 종료되지 않고 계속 다음 작업에 재사용되는 것을 확인할 수 있습니다.
References
https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Executors.html#newSingleThreadExecutor--
https://velog.io/@haero_kim/Java-Thread-Pool-개념과-동작원리
'Java' 카테고리의 다른 글
자바 성능 튜닝 끄적끄적 (0) | 2024.02.17 |
---|---|
[Java] 스레드 동기화 - Synchronized (0) | 2022.09.11 |
[Effective java] equals를 재정의하면 hashCode도 재정의해야 한다. (0) | 2022.02.18 |
[Effective java] equals 일반 규약 (0) | 2022.02.17 |