[Spring] Thread Pool 사용하기(feat. Scheduler)

rara_kim·2022년 9월 14일
2

Spring

목록 보기
12/20
post-thumbnail

앞의 글에서 스프링에서 스케줄링 하는 내용을 다뤘는데, 스케줄링으로 실행되어야 할 기능이 여러개 일 경우에는 한 가지 더 고려해야하는 것이 있다.
바로 Thread Pool이다.

@Component
public class TestScheduler {
	
    @Scheduled(fixedDelay = 1000)   //작업이 끝나는 시점으로부터 1초 후에 수행
    public void test1() throws InterruptedException {
    	Thread.sleep(10000);      // 10초 대기
        System.out.println("Test1: " + LocalDateTime.now());
        
    }
    
      @Scheduled(fixedDelay = 1000)   //작업이 끝나는 시점으로부터 1초 후에 수행
    public void test2() {
        System.out.println("Test2: " + LocalDateTime.now());   
    }
}

위의 코드를 봤을 땐 test1()이 한번 시행될 때 test2()가 10번 시행되어야 할 것 처럼 보이지만 실제로 실행시켜보면 결과를 그렇지 않다.

테스트1의 작업이 종료되어야지만 테스트2의 작업이 실행되는 것을 볼 수 있다.
그래서 테스트2의 경우에는 작업대기가 없지만 테스트1과 같이 10초에 한번씩 작업이 실행된다.
다시말해, 스케줄러로 2개 이상의 작업을 실행하려고 할 때 실행되어야 할 작업이 실행되지 않을 것이라고 추론할 수 있다.

이유는 바로, 스케줄러가 한 개의 쓰레드로 동작하는 것을 기본으로 하기 때문이다.
그렇게 되면 스케줄러로 2개 이상의 작업을 설정한 경우, 해야할 작업은 밀려있지만 실행해야 할 쓰레드가 하나밖에 없게 되는 것이다.
이것은 작업을 해야할 일꾼인 쓰레드를 늘리는 것으로 해결 할 수 있다.

Thread Pool 이란?

Thread Pool은 여러 개의 쓰레드를 유지하고 관리하기 위해 사용된다.
쓰레드는 한번 생성 시키고 소멸하면 굉장히 많은 리소스를 소모하게 되기때문에 매번 쓰레드를 생성시키고 없애기 보다는, Thread Pool에서는 설정된 크기의 쓰레드를 만들어 놓고 해당 쓰레드들을 계속해서 재사용할 수 있도록 관리를 해준다.

Thread Pool의 적정 사이즈는?

그렇다면 Thread Pool의 사이즈는 얼마가 적당할까?
쓰레드를 불필요하게 많이 만들게 되면 메모리의 낭비가 심해질 것이고, 너무 적은 수의 쓰레드를 만들게 되면 효율성이 떨어질 것이다.
쓰레드의 개수는 공식으로 정해진 것은 아니지만 코드로 고정시키키보다는 서비스가 실행되는 CPU의 코어 개수에 따라 유동적으로 생성될 수 있도록 해주는 것이 좋다.

  • CPU 처리가 많은 경우
    CPU의 코어를 N개라고 했을 때, N + 1만큼의 쓰레드를 생성해주면 최적에 가까운 성능을 낼 수 있다고 보기도 한다.

  • I/O 작업이 많은 경우
    N * 2만큼의 쓰레드를 생성해주기도 한다.

많이 생성한다고 좋은 것이 아니라 어떠한 작업을 처리하느냐가 기준이 될 수 있다.

스프링에서의 Thread Pool 설정

@Configuration
public class SchedulerConfig implements SchedulingConfigurer {

	@Override
	public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        // Thread Pool 설정
		ThreadPoolTaskScheduler threadPool = new ThreadPoolTaskScheduler();  
 
        // Thread 개수 설정
		int n = Runtime.getRuntime().availableProcessors();
		threadPool.setPoolSize(n);
		threadPool.initialize();
        
		taskRegistrar.setTaskScheduler(threadPool);
	}
}

위와 같이 Thread Pool을 설정해주고 아까와 같은 코드를 실행시켜주면, 테스트2가 1초에 한번씩 정상적으로 실행되고 테스트1은 10초에 한번씩 실행되는 것을 볼 수 있다.
그리고 쓰레드 이름을 확인했을 때 아까와는 다르게 Thread Pool에 있는 여러 쓰레드들로 작업이 실행되는 것을 확인할 수 있다.

profile
느리더라도 꾸준하게

0개의 댓글