ThreadPoolExecutor 정책 설정 및 응용 장면

Thread PoolExecutor 는 비동기 작업 을 처리 하 는 인터페이스 로 하나의 스 레 드 탱크 와 하나의 작업 대기 열 로 이해 할 수 있 습 니 다.Executor Service 대상 에 제출 된 작업 은 작업 팀 에 넣 거나 스 레 드 탱크 의 스 레 드 에 직접 실 행 됩 니 다.ThreadPoolExecutor 는 구조 적 인 파 라 메 터 를 조정 하여 서로 다른 처리 전략 을 설정 하 는 것 을 지원 합 니 다.본 고 는 주로 자주 사용 하 는 전략 설정 방법 과 응용 장면 을 소개 합 니 다.
Thread PoolExecutor 의 처리 논리
우선 Thread PoolExecutor 구조 함수 의 정 의 를 살 펴 보 겠 습 니 다.
public ThreadPoolExecutor(int corePoolSize,  //         
                              int maximumPoolSize,   //         
                              long keepAliveTime,      //  KeepAlive  ,                ,idle              
                              TimeUnit unit,              //  KeepAlive    
                              BlockingQueue workQueue,    //    
                              ThreadFactory threadFactory,                  //         
                              RejectedExecutionHandler handler)          //         handler

ThreadPoolExecutor 가 스 레 드 탱크 와 대기 열 에 대한 사용 방식 은 다음 과 같 습 니 다.
  • 스 레 드 탱크 에서 사용 가능 한 스 레 드 를 가 져 와 작업 을 수행 합 니 다.사용 가능 한 스 레 드 가 없 으 면 ThreadFactory 를 사용 하여 새로운 스 레 드 를 만 듭 니 다.스 레 드 수가 corePoolSize 제한
  • 에 이 를 때 까지.
  • 스 레 드 탱크 스 레 드 수가 core PoolSize 에 도달 하면 새로운 작업 은 대기 열 에 들 어가 더 많은 작업 을 수용 할 수 없 을 때 까지
  • 대기 열 에서 더 많은 작업 을 수용 할 수 없 을 때 새로운 스 레 드 를 만 들 것 입 니 다.스 레 드 수가 maxinumPoolSize 제한
  • 에 이 를 때 까지.
  • 스 레 드 수가 maxinum PoolSize 제한 에 도달 하면 새 작업 이 거부 되 고 Rejected Execution Handler 를 호출 하여 처리 합 니 다
  • 세 가지 상용 Thread PoolExecutor
    Executors 는 자주 사용 하 는 Executor 서 비 스 를 만 드 는 공장 방법 을 제공 합 니 다.각각 Fixed ThreadPool,Cached ThreadPool,Single ThreadExecutor 입 니 다.이 세 가지 ThreadPoolExecutor 는 모두 ThreadPoolExecutor 구조 함 수 를 호출 하여 만 든 것 으로 매개 변수 가 다르다 는 것 과 차이 가 있다.
    FixedThreadPool-스 레 드 탱크 크기 고정,퀘 스 트 대기 열 무한
    다음은 Executors 류 new Fixed ThreadPool 방법의 소스 코드 입 니 다.
        public static ExecutorService newFixedThreadPool(int nThreads) {
            return new ThreadPoolExecutor(nThreads, nThreads,
                                          0L, TimeUnit.MILLISECONDS,
                                          new LinkedBlockingQueue());
        }

    corePoolSize 와 maximumPoolSize 가 같은 값 으로 설정 되 어 있 음 을 볼 수 있 습 니 다.이 때 스 레 드 수량 이 핵심 스 레 드 수량 보다 많은 경 우 는 존재 하지 않 기 때문에 KeepAlive 시간 설정 은 유효 하지 않 습 니 다.작업 대기 열 은 크기 를 제한 하지 않 는 링크 드 BlockingQueue 를 사용 합 니 다.무한 대기 열 이기 때문에 수용 할 수 있 는 작업 수량 은 상한 선 이 없습니다.
    따라서 Fixed ThreadPool 의 행동 은 다음 과 같다.
  • 스 레 드 탱크 에서 사용 가능 한 스 레 드 를 가 져 와 작업 을 수행 합 니 다.사용 가능 한 스 레 드 가 없 으 면 ThreadFactory 를 사용 하여 새로운 스 레 드 를 만 듭 니 다.스 레 드 수가 nThreads
  • 에 도달 할 때 까지.
  • 스 레 드 탱크 스 레 드 수가 nThreads 에 도달 하면 새로운 작업 이 대기 열 에 들 어 갑 니 다
  • Fixed ThreadPool 의 장점 은 모든 임 무 를 수행 할 수 있 고 새로운 임 무 를 영원히 거절 하지 않 는 다 는 것 이다.또한 대기 열 수가 제한 되 지 않 아 작업 수행 시간 이 무한 연장 되 는 극단 적 인 상황 에서 메모리 문제 가 발생 하 는 것 이 단점 이다.
    SingleThreadExecutor-스 레 드 탱크 크기 가 1 로 고정 되 어 있 으 며,작업 대기 열 이 무한 합 니 다.
        public static ExecutorService newSingleThreadExecutor() {
            return new FinalizableDelegatedExecutorService
                (new ThreadPoolExecutor(1, 1,
                                        0L, TimeUnit.MILLISECONDS,
                                        new LinkedBlockingQueue()));
        }

    이 공장 방법 에 서 는 무한 링크 드 BlockingQueue 를 사용 하고 스 레 드 수 를 1 로 설정 하 였 으 며,이 외 에 도 FinalizableDelegated Executor Service 류 를 사용 하여 포장 하 였 다.이 포장 류 의 주요 목적 은 Thread PoolExecutor 에서 스 레 드 수량 을 동적 으로 수정 하 는 기능 을 차단 하기 위해 Executor Service 에서 제공 하 는 방법 만 보류 하 는 것 입 니 다.단일 스 레 드 처리 이지 만 스 레 드 가 이상 처리 등 으로 인해 종 료 될 때 Thread PoolExecutor 는 자동 으로 새로운 스 레 드 를 만들어 작업 을 계속 합 니 다.
    SingleThreadExecutor 는 논리 적 으로 단일 스 레 드 로 작업 을 처리 해 야 하 는 장면 에 적용 되 며,무한 한 링크 드 BlockingQueue 는 새로운 작업 이 대기 열 에 들 어 갈 수 있 도록 해 주 며 거부 되 지 않 습 니 다.단점 은 Fixed ThreadPool 과 마찬가지 로 작업 을 무한 대기 할 때 메모리 문제 가 발생 할 수 있 습 니 다.
    CachedThreadPool-스 레 드 풀 무한대(MAX INT),대기 행렬 길이 1
        public static ExecutorService newCachedThreadPool() {
            return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                          60L, TimeUnit.SECONDS,
                                          new SynchronousQueue());
        }

    SynchronousQueue 는 하나의 요소 만 있 는 대기 열 입 니 다.대기 열 에 있 는 요소 가 이동 할 때 까지 대기 해 야 합 니 다.핵심 스 레 드 수 는 0 으로 모든 작업 이 먼저 대기 열 에 들 어 가 는 것 을 의미 합 니 다.최대 스 레 드 수 는 Integer.MAX 입 니 다.VALUE,스 레 드 수량 에 제한 이 없다 고 볼 수 있 습 니 다.KeepAlive 시간 이 60 초 로 설정 되 어 있 으 며,작업 이 없 을 때 스 레 드 가 60 초 를 기다 린 후 종료 한 다 는 뜻 입 니 다.CachedThreadPool 에서 작업 을 처리 하 는 전략 은 제출 한 작업 이 하나의 스 레 드 를 즉시 배정 하여 실행 하 는 것 입 니 다.스 레 드 탱크 의 스 레 드 수량 은 작업 수의 변화 에 따라 자동 으로 확장 되 고 줄 어 들 며 작업 수행 시간 이 무한 연장 되 는 극단 적 인 상황 에서 너무 많은 스 레 드 를 만 듭 니 다.
    세 가지 Executor 서비스 특성 총화
    유형
    핵심 루틴 수
    최대 스 레 드 수
    생존 시간 유지
    작업 대기 열
    작업 처리 정책
    FixedThreadPool
    고정 크기
    고정 크기(핵심 스 레 드 수 와 동일)
    0
    LinkedBlockingQueue
    스 레 드 탱크 크기 가 고정 되 어 있 습 니 다.사용 가능 한 스 레 드 가 없 을 때 작업 은 대기 열 에 넣 어 기다 리 고 대기 열 길 이 는 제한 이 없습니다.
    SingleThreadExecutor
    1
    1
    0
    LinkedBlockingQueue
    Fixed ThreadPool 과 마찬가지 로 스 레 드 탱크 의 크기 가 1 인 것 과 달리 업무 논리 상 1 개의 스 레 드 만 처리 할 수 있 는 장면 에 적용 된다.
    CachedThreadPool
    0
    Integer.MAX_VALUE
    1 분
    SynchronousQueue
    스 레 드 탱크 의 수량 이 무한 합 니 다.새 작업 은 스 레 드 를 직접 할당 하거나 생 성하 여 실 행 됩 니 다.
    사용자 정의 ThreadPoolExecutor
    Thread PoolExecutor 의 구조 함 수 를 수정 하여 작업 처리 전략 을 사용자 정의 할 수 있 습 니 다.예 를 들 어 직면 한 업 무 는 데 이 터 를 HBase 에 비동기 로 기록 하 는 것 입 니 다.HBase 가 심각하게 시간 을 초과 할 때 실패 하고 로 그 를 기록 하여 나중에 다시 쓸 수 있 도록 합 니 다.이러한 응용 장면 에 대해 Fixed ThreadPool 을 사용 하면 HBase 서비스 가 심각하게 시간 을 초과 할 때 대기 열 이 무한 증가 하고 메모리 문 제 를 일 으 킬 수 있 습 니 다.Cached ThreadPool 을 사용 하면 스 레 드 수가 무한 증가 합 니 다.이러한 장면 에 대해 저 희 는 ExecutorService 를 설정 하여 길이 제한 이 있 는 대기 열 과 최대 스 레 드 개 수 를 제한 하 는 스 레 드 풀 을 사용 할 수 있 습 니 다.또한 Rejected Execution Handler 를 설정 하여 작업 이 거부 되 는 상황 을 처리 할 수 있 습 니 다.
    우선 RejectedExecutionHandler 를 정의 합 니 다.
    public class MyRejectedExecutionHandler implements RejectedExecutionHandler {
    
            @Override
            public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
                //           ,       
            }
        }

    ThreadPoolExecutor 만 들 기:
    ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
                    10,                                                               //        10
                    30,                                                              //         30
                    30, TimeUnit.SECONDS,                              //           idle 30      
                    new ArrayBlockingQueue(100),       //     100
                    new MyRejectedExecutionHandler()                //           
            );

    이렇게 설정 한 후 작업 처리 함수 가 장시간 걸 리 는 경우 다음 과 같은 현상 이 발생 합 니 다.
  • 스 레 드 탱크 스 레 드 수량 이 핵심 스 레 드 수 에 달 하고 Array BlockingQueue 에 작업 을 넣 습 니 다
  • Array BlockingQueue 가 상한 에 도달 하여 새로운 스 레 드 를 만들어 처리 합 니 다
  • 스 레 드 탱크 의 스 레 드 수량 이 30 개 에 달 하고 MyRejected Execution Handler 를 호출 하여 새로 제출 한 작업 을 처리 합 니 다
  • 총결산
  • 제출 한 모든 작업 이 수행 되도록 보장 해 야 하 는 경우 Fixed ThreadPool
  • 을 사용 합 니 다.
  • 한 스 레 드 로 만 작업 처 리 를 할 수 있 도록 제한 하면 SingleThreadExecutor
  • 를 사용 합 니 다.
  • 제출 한 퀘 스 트 가 가능 한 한 빨리 스 레 드 를 배정 하여 실행 하려 면 CachedThreadPool
  • 을 사용 하 십시오.
  • 업무 상 임무 수행 이 실 패 했 거나 임무 수행 과정 이 너무 길 어서 다른 업무 에 영향 을 줄 수 있 는 응용 장면 이 나타 날 수 있 으 면 스 레 드 수량 을 제한 하 는 스 레 드 탱크 와 길 이 를 제한 하 는 대기 열 을 사용 하여 잘못 처리 할 수 있다.
  • 좋은 웹페이지 즐겨찾기