ThreadPoolTaskExecutor 옵션 설명

Bonjugi·2023년 2월 15일
0

TaskExecutor 만들때 이런식으로 bean에 등록해서 종종 쓴다.
그런데 항상 옵션이 헷갈린다.
생각보다 비슷하지만 틀리게 쓴 블로그도 많아서 이번기회에 정리 해 둔다.

@Bean
public Executor getAsyncExecutor() {
    ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
    
    // 1. 
    executor.setCorePoolSize(2);
    executor.setMaxPoolSize(4);
    executor.setQueueCapacity(5);
    executor.setRejectedExecutionHandler(new CallerRunsPolicy());
    
    // 2.
    executor.setTaskDecorator(new MdcTaskDecorator());
    
	// 3.
    // shutdown 될때 task가 모두 처리 될때까지 대기한다.
    // 이때 무한정 기다릴수 없으니 30초까지 기다린다.
    executor.setWaitForTasksToCompleteOnShutdown(true);
    executor.setAwaitTerminationSeconds(30);

	// 4. 얜 생략해도 bean 이름으로 자동 등록 되어 괜찮다.
    // executor.setThreadNamePrefix("t-");


    executor.initialize();
    return executor;
}

들어가기에 앞서 Pool 에 대해서.
ThreadPoolTaskExecutor 를 디버깅 해보면 다음과 같은 값들을 볼수 있다.
일단 용어만 눈에 넣어두자.

[Running, pool size = 0, active threads = 0, queued tasks = 0, completed tasks = 0]
  • Excutor의 상태
  • 쓰레드 풀의 수
  • 활성 쓰레드 수
  • 큐에 있는 태스크 수
  • 완료된 태스크 수

1. CorePoolSize(2), MaxPoolSize(4), QueCapacity(5), CallerRunsPolicy

기본 풀의 수를 2로 등록 한 것이다.
처음 2개의 태스크를 등록하면 풀 2개가 처리하여 pool size = 2 가 된다.
큐 케파가 5개 짜리니까, 5개의 태스크를 더 밀어넣을수 있다.

큐도 풀도 꽉찬 상태에서는 풀을 MaxPoolSize(4) 까지는 추가로 등록한다.
이미 풀 2개가 더있었으니 2개의 풀을 더 등록할수 있어서 2개의 태스크를 더 받을수 있다.
3개부터는 reject 되는데, 아래의 옵션으로 처리 정책을 정할수 있다.

setRejectedExecutionHandler(new CallerRunsPolicy()); 

CallerRunsPolicy 이외에 다른 옵션들도 있지만 설명 생략한다.
CallerRunsPolicy는, reject 됐을때 Caller 가 처리하고 태스크는 지운다.

높은 스루풋에 의해 MaxPoolSize 만큼 늘어난 pool은, 시간이 지나면 다시 CorePoolSize 줄어든다.
사용되지 않는 풀이 정리 대상이 되는데, 대략 10초정도 안쓰면 정리되더라. (정확한 알고리즘은 모르겠다)

2. TaskDecorator

잘 쓰여진곳이 많아서 생략

3. WaitForTasksToCompleteOnShutdown, AwaitTerminationSeconds

가장 정리하고 쓰고싶던 옵션 이다.
잘못(또는 대강) 설명된 곳이 많았다.

아래 2개 옵션은 병렬적으로 처리된다고 하지만 막상 써보면 페어한 옵션이다.

// shutdown 될때 task가 모두 처리 될때까지 대기한다.
// 이때 무한정 기다릴수 없으니 30초까지 기다린다.
executor.setWaitForTasksToCompleteOnShutdown(true);  // 1
executor.setAwaitTerminationSeconds(30);             // 2

예를들어 1번 옵션은 대략 "task가 모두 종료 될때까지 기다린다" 는 옵션이다.
그런데 막상 1번 옵션만 설정하고 실험해보면 즉시 종료 되더라.

2번 옵션도 확인 해본다.
1번이 true 인 경우, task가 모두 종료 될때까지 무한정 기다릴수 없으니 30초 까지만 기다리겠다는 옵션이다.
타임아웃 용도로 보면 되는데, 기본값이 0이었기 때문에 즉시 종료 되었던것.
사실상 1,2번을 같이 설정 해줘야 제대로 동작한다.

0개의 댓글

관련 채용 정보