ThreadPoolExecutor 작동 방식

60jong·2023년 12월 30일
0

Java

목록 보기
14/14

Tomcat과 같은 thread per request 전략을 사용하는 애플리케이션에 많은 요청이 밀려들었다. 그 때마다 thread를 생성하고 소멸시킨다면 자원이 많이 낭비되지 않을까?

Thread Pool

이 문제를 해결하기 위한 방법 중 하나로 Thread Pool이 있다. 미리 Thread를 생성해두고, Task를 수행할 Thread를 할당하고 수거함으로써 자원 낭비를 줄일 수 있게 된다.

이처럼 생성/소멸에 자원이 많이 소모되는 환경에서 이를 미리 만들어 둔 그룹을 pool이라고 한다.
Thread Pool 뿐 아니라 DB와의 Connection을 만들어 둔 Connection Pool도 있다.

그렇다면 Java에서 이런 Thread Pool을 어떻게 생성하고 관리할까?

Executor

Java 5를 기점으로 Executor, ExecutorService 라는 인터페이스가 등장했다.

public interface Executor {

	void execute(Runnable runnable);
}
  • ExecutorThread Pool에 Task를 실행시키는 추상화, Functional interface 형식
  • ExecutorService extends Executor는 Task 실행에서 더 나아가 Thread Pool이 가져야 할 기능의 추상화이다.

우리는 이 인터페이스의 구현체 중 하나인 ThreadPoolExecutor살펴보자.

ThreadPoolExecutor

일단 ThreadPoolExecutor의 계층 구조는 위와 같다.

객체 생성 방식은 크게 두 가지이다.

  • new + 생성자
  • Executors의 팩토리 메서드 (single / fixed / cached)

우리는 핵심이 되는 "thread가 생성되고 소멸되는 과정" 을 알아보자.

어차피 Executors에 의한 3가지 ThreadPoolExecutorcorePoolSize, MaxPoolSize, keepAlive 인자 차이일 뿐이다.

주요 용어

  • corePoolSize : 쓰레드 풀이 유지할 쓰레드 수
  • maxPoolSize : 쓰레드 풀이 가질 수 있는 최대 쓰레드 수
  • keepAlive : 쓰레드가 task 종료 후 살아있을 시간 (corePoolSize 이상 일 때)
  • queueSize : waitingQueue 사이즈

ThreadPoolExecutor 작동 방식

Task가 요청됐을 때

  • active thread가 corePoolSize 미만이라면, 새 thread를 생성

  • corePoolSize <= active <= MaxPoolSize 라면 Task를 Queue에 추가

    • 이때 Queue가 가득 찼다면 새 thread 생성

      • 단, active < MaxPoolSize일 경우에만이다.

      • Queue가 가득 차고, thread 수가 maxPoolSize이라면 해당 Task는 Reject가 된다. ... RejectedExecutionException

corePoolSize를 넘는 Thread

여기서 keepAlive 인자가 사용된다. Thread Pool은 불필요한 자원 소모를 방지하기 위해, corePoolSize를 넘는 Thread는 Task 종료 후 keepAlive가 지나면 이 thread를 소멸시킨다.

결론

주요한 특징은 corePoolSize 유지 & 새 Thread 생성 보다는 Queue에 추가

profile
울릉도에 별장 짓고 싶다

0개의 댓글