Spring/Issue

Scheduler Thread Pool 사용하기

블로그 주인장 2024. 1. 8.

이전 글에서 스프링에서 스케쥴링을 하는 내용을 다뤘다.

https://miiro-under.tistory.com/261

 

레디스와 스케쥴러를 이용한 조회수 증가

Issue 이전 포스팅에서 조회수 기능을 중복 방지할 수 있도록 세션(Session)을 사용했다. https://miiro-under.tistory.com/260 조회수 기능 구현하기 - 중복 방지(Session) Issue 이전 포스팅에서 조회수 기능을 중

miiro-under.tistory.com

 

스케쥴링을 실행되어야 할 기능이 여러 개일 경우 사용해야할 것이 Thread Pool 이다.

 

위의 프로젝트에서 스케쥴러를 2개를 사용할 예정인데 예제를 이용하여 테스트를 진행해보겠습니다.

 

예제 코드는 해당 링크에서 확인하시면됩니다 : github

코드 구현

Thread Pool 을 이용하여 테스트 코드를 만들어보겠습니다.

 

위의 코드는 1초에 한번씩 문자열을 출력하는 작업을 하는 코드이다.

 

코드를 봤을 때는 reportCurrentTIme()이 한번 실행되고 reportCurrentTime2()가 10번 시행되어야할 것 처럼 보이지만

실제로 실행시켜보면 결과는 정반대의 결과가 나온다.

 

결과

 

테스트1의 작업이 종료되어야지만 테스트2의 작업이 실행되는 것을 볼 수 있다.

그래서 테스트2의 경우에는 작업대기가 없지만 테스트1과 같이 10초에 한 번씩 작업이 실행된다.

정리하면, 스케줄러 2개 이상의 작업을 실행하려고 할 때 실행되어야 할 작업이 실행되지 않을 것이라고 추론할 수 있다.

 

이유는 스케쥴러가 한 개의 쓰레드로 동작하는 것을 기본으로 하기 때문이다.

 

그렇게 되면 스케쥴러가 2개 이상의 작업을 설정한 경우, 해야할 작업은 밀려있지만 실행해야 할 쓰레드가 하나밖에 없게 된다.

이는, 작업을 해야할 일꾼인 쓰레드를 늘리는 것으로 해결이 가능하다.

 

Thread Pool 이란?

Thread Pool은 여러 개의 쓰레드를 유지하고 관리하기 위해 사용된다.

쓰레드는 한 번 생성 시키고 소멸하면 굉장히 많은 리소스를 소모하게 되기에 매번 쓰레드를 생성시키고 없애는 것보다,

Thread Pool 에서는 설정된 크기의 쓰레드를 만들어 놓고 해당 쓰레드들을 계속해서 재사용할 수 있도록 관리해준다.

 

Thread Pool 의 적정 사이즈는?

쓰레드를 불필요하게 많이 만들게 되면 메모리의 낭비가 심해지고,

너무 적은 수의 쓰레드를 만들게 되면 효율성이 떨어질 것이다.

 

쓰레드의 개수는 공식적으로 정해진 것은 아니지만 코드로 고정시키기보다는

서비스가 실행되는 CPU의 코어 개수에 따라 유동적으로 생성될 수 있도록 해주는 것이 좋다.

 

CPU의 코어를 N개라고 가정해보겠습니다.

 

[CPU 처리가 많은 경우]

N + 1 만큼 쓰레드를 생성해주면 최적에 가까운 성능을 낼 수 있다고 보기도 한다.

 

[I/O 작업이 많은 경우]

N * 2 만큼의 쓰레드를 생성해주기도 한다.

 

ref. I/O 란?

하드웨어 장치를 통한 입출력 정보를 컴퓨터에서 구동 중인 어플리케이션에서 컨트롤하고자 할 때 사용하는 일종의 인터페이스이다.

 

스프링 스케쥴러에서 Thread Pool 사용하기

 

1. SchedulingConfigurer를 구현한 클래스를 만든다.

 

2. configureTask(ScheduledTaskRegistrar taskRegistrar) 메소드를 Overrride 한다.

 

3. 메소드 안에서 ThreadPoolTaskScheduler 인스턴스를 생성한다.

 

4. ThreadPoolTaskScheduler에 쓰레드 갯수를 Setting 하고 initialize(초기화) 한다.

 

5. ThreadPoolTaskScheduler를 매개변수인 taskRegistrar에 넣는다.

 

* 현재는 테스트이기 때문에 setPoolSize를 쓰레드 갯수로 초기화해준다.

 

 

위와 같은 Thread Pool을 설정해주고 아까와 같은 코드를 실행해보겠습니다.

 

reportCurrentTime2()가 1초에 한 번씩 정상적으로 실행되고 reportCurrentTime()은 10초에 한 번씩 실행되는 것을 확인할 수 있다.

아까와는 다르게 Thread Pool에 있는 여러 쓰레드(11번, 4번 ,12번) 들로 작업이 실행되는 것을 확인할 수 있다.

 

 

한 줄 마무리

스케쥴러를 여러 개를 사용할 때는 Thread Pool을 이용해야한다는 것을 알았다. 그러면서 스케쥴러가 싱글 스레드라서 하나의 작업이 마무리가 되야 다음 작업이 가능하기에 멀티쓰레드 형식으로 변환할 수 있다는 것을 알게되었다.이를 이용해서 실제 프로젝트에 적용해서 구현해보겠습니다.

 

 

본 포스트는 작성자가 공부한 내용을 바탕으로 작성한 글입니다.
잘못된 내용이 있을 시 언제든 댓글로 피드백 부탁드리겠습니다.
항상 정확한 내용을 포스팅하도록 노력하겠습니다.

반응형

댓글