! 미리 알아갈 용어 !
Process
: 운영체제에서 하나의 어플리케이션
Thread
: process에서 하나의 작업
동시성(Concurrency)은 싱글 코어에서 멀티 스레드를 동작
시키기 위한 방식입니다. 실제로 여러 작업이 동시에 이루어지는 것처럼 보이지만, 실제로는 한 시점에 하나의 스레드만 실행되는 방식으로 처리
됩니다.
병렬성(Parallelism)은 멀티 코어에서 멀티 스레드를 동작
시키는 방식으로, 각각의 코어는 독립적으로 하나 이상의 스레드를 실행
할 수 있으며, 이를 통해 처리 속도를 크게 향상시킬 수 있습니다.
대표적인 예
웹 서버웹 애플리케이션의 경우, HTTP 요청의 수신과 처리는 톰캣과 같은 서블릿 컨테이너에 의해 이루어집니다. 톰캣은 요청을 처리하기 위해 내부적으로 쓰레드 풀을 사용하고, 이 쓰레드 풀에서 쓰레드들은 미리 생성되어 있으며, 각 HTTP 요청이 들어올 때마다 풀에서 쓰레드 하나가 할당되어 요청을 처리합니다.
그렇다면 Thread
를 계속 늘려가는 건 좋을까요 ?
병렬 작업 처리가 많아지면
스레드 개수가 증가
하고, 그에 따른 스레드 생성과 스케줄링으로 인해 CPU의 메모리 사용량이 늘어납니다.
이는 즉, 애플리케이션의 성능 저하로 이어집니다.작업 처리에 사용되는 스레드를 제한된 개수만큼 정해 놓고 작업 큐에 들어오는 작업들을 하나씩 스레드가 맡아 처리
합니다.작업 처리가 끝난 스레드는 다시 작업 큐에서 새로운 작업을 가져와 처리
합니다.스레드의 전체 개수는 일정하며 애플리케이션의 성능도 저하되지 않습니다.
간단히,
Thread Pool
은 작업 처리에 사용되는 스레드를 제한된 개수만큼 정해놓고, 작업 큐(Queue)에 들어오는 작업들을 하나씩 Thread가 맡아 처리하는 것을 의미합니다.
Java17의 경우, 멀티 스레딩을 관리하기 위해 주로 ExecutorService
인터페이스와 구현체인 ThreadPoolExecutor
를 사용해 효율적으로 스레드 풀을 생성하고 관리할 수 있습니다.
Single Thread Poll
ExecutorService executorService = Executors.newSingleThreadExecutor();
Worker Thread
Fixed Thread Pool
ExecutorService executorService = Executors.newFixedThreadPool(int nThreads); //고정 크기 스레드 풀
Worker Thread
를 사용하며, 모든 Thread
를 사용 중이라면 Queue
에 쌓여 대기한다.Thread
를 생성하여 대체한다.Cached Thread Pool
ExecutorService executorService = Executors.newCachedThreadPool(); //자동 스레드 재생 기능을 갖춘 무제한 스레드 풀
Thread
를 생성하며, 이전에 생성된 Thread
가 존재하면 재사용합니다.Thread
가 유지합니다.Scheduler Thread Pool
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(int corePoolSize);
Work Stealing Thread Pool
ExecutorService executorService = Executors.newWorkStealingPool(int parallelism);
parallelism
을 지원할만큼 충분한 Thread
를 유지하고 여러 Queue
을 사용하여 경합을 줄입니다.Thread
를 동적으로 늘리고 줄입니다.<참고 자료>
java17 공식문서
허원철의 개발 블로그
제이온