Illie
[JAVA] Executor 전략 본문
서론
Executor는 스레드를 효율적으로 사용할 수 있도록 도와준다
기본적으로 설정해놓은 스레드 수 만큼을 활성화해놓고 있다가,
활성화되어있는 스레드가 모두 사용중이라면
1. Queue에 넣어 대기 시키고 차례를 기다리던가
2. 스레드를 초과해서 생성해서 작업을 진행하던가
3. Rejection을 하던가
선택할 수 있다.
서비스의 목적에 맞게 맞는 전략을 세우면 되는데,
대표적으로 어떤 전략이 있는지 알아보고자 한다
본론1
단일 스레드 풀 전략
스레드 풀에 기본 스레드 1개만 사용한다
즉, 추가적으로 들어오는 요청은 모두 대기 상태가 된다
new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>())
고정 풀 전략
단일 스레드 풀 전략과 비슷하다
하나 다른 점은 스레드풀을 하나 초과로 사용한다는 점만 다르다
장점은 스레드의 수가 고정되어있기 때문에 CPU, 메모리 리소스가 어느정도 예측 가능해진다
다만, 요청이 처리되는 시간보다 쌓이는 시간이 더 빠르게 된다면... 끔찍한 상황이 초래된다
new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>())
캐시 풀 전략
기본 스레드를 사용하지 않고, 생존주기를 가진 초과 스레드만 사용한다
그리고 초과 스레드의 생존주기를 지정해주어 스레드를 유동적으로 사용한다
되게 독특한게, 대기하지 않도록 SynchronouQueue를 사용한다는 점이다
new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.MILLISECONDS, new SynchronousQueue<Runnable>())
주의
다음과 같이 대기 큐의 사이즈를 무한대로 줘버리면,
스레드가 절대절대 최대 사이즈만큼 늘어나지 않게 된다
new ThreadPoolExecutor(100, 200, 60, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>())
본론2
무한히 모든 것을 할 수 있다면 상관이 없겠지만,
현실에는 CPU, 메모리 자원이라는 제약이 있다
Executor을 미리 정의하여 예외를 처리할 수 있다
new ThreadPoolExecutor(1, 1, 0, TimeUnit.SECONDS, new SynchronousQueue<>(), "__EXCEPTION_HERE__");
AbourPolicy(default)
RejectedExecutionException을 발생시킨다
catch에서 잡아서 다시 시도를 하거나, 다시 시도하라고 알려주거나 하면 된다
DiscardPolicy
새로운 작업을 조용히 버린다...
사실 이건 언제 사용하면 좋을지... 모르겠다
그래도 어떻게든 개발자가 처리해야 하는거 아닌감...?
CallerRunsPolicy
호출한 스레드가 직접 작업을 수행하도록 한다
이 방법은 생산속도를 조절할 수 있다는 장점이 있다
그 외
다음과 같이 코드로 구현하여 사용자가 직접 거절 정책을 활용할 수 있다
static class CustomRejectedExecutionHandler implements RejectedExecutionHandler {}
결론
자신의 상황에 맞는 알맞은 관리전략을 선택하자!
'JAVA' 카테고리의 다른 글
[JAVA] try-with-resources (0) | 2024.10.13 |
---|---|
[JAVA] 싱글톤 (1) | 2024.09.12 |