자바 스 레 드 탱크 의 각 매개 변 수 는 어떻게 합 리 적 으로 설정 합 니까?

머리말
개발 과정 에서 많은 장면 들 이 스 레 드 탱크 를 사용 해 야 한다.매번 업무 장면 에 따라 스 레 드 탱크 의 각 인 자 를 설정 합 니 다.
이틀 동안 또 수요 가 생 겼 으 니 차라리 편 의 를 정리 한 후에 다시 만나면 직접 보고 사용 할 수 있다.
비록 업무 장면 에 따라 각 매개 변수의 값 을 설정 하지만 어떤 변 화 는 그 종 류 를 떠 나 지 않 고 그의 원 리 를 파악 하 는 것 이 스 레 드 탱크 를 어떻게 잘 사용 하 는 지 에 중요 한 역할 을 한다.
그럼 우 리 는 이어서 스 레 드 탱크 의 분석 을 진행 할 것 이다.
2.ThreadPoolExecutor 의 중요 한 매개 변수
우선 Thread PoolExecutor 의 중요 한 매개 변수 구조 기 를 살 펴 보 겠 습 니 다.

public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue,
                          ThreadFactory threadFactory,
                          RejectedExecutionHandler handler) {
    ...
}
1.코어 풀 사이즈:핵심 스 레 드 수
이것 은 가장 중요 한 매개 변수 일 것 이 므 로 어떻게 합 리 적 으로 설정 하 느 냐 가 매우 중요 하 다.
4.567917.핵심 스 레 드 는 계속 살아 남 고 임 무 를 수행 해 야 하지 않 습 니 다4.567917.스 레 드 수가 핵심 스 레 드 보다 적 을 때 스 레 드 가 비어 있어 도 스 레 드 풀 은 새로운 스 레 드 처 리 를 우선 만 듭 니 다
  • allowCoreThreadTimeout=true(기본 false)를 설정 하면 핵심 스 레 드 가 시간 을 초과 하여 닫 힙 니 다
  • 어떻게 전 제 를 설정 하 는 지 우 리 는 CPU 밀집 형 과 IO 밀집 형의 차 이 를 잘 알 아야 한다.
    (1)CPU 밀집 형
    CPU 집약 형 은 컴 퓨 팅 집약 형 이 라 고도 하 는데 시스템 의 하 드 디스크,메모리 성능 이 CPU 보다 훨씬 좋 은 것 을 말한다.이때 시스템 운영 의 대부분 상황 은 CPU Loading 100%이 고 CPU 는 읽 기/쓰기 I/O(하 드 디스크/메모리)이 며 I/O 는 짧 은 시간 에 완성 할 수 있 으 며 CPU 는 처리 해 야 할 연산 이 많아 CPU Loading 이 높다.
    다 중 프로그램 시스템 에서 대부분의 시간 을 계산,논리 적 판단 등 CPU 동작 을 하 는 프로그램 을 CPU bound 라 고 부른다.예 를 들 어 원주율 을 소수점 천 자리 이하 로 계산 하 는 프로그램 은 실행 과정 에서 대부분 삼각함수 와 루트 번 호 를 계산 하 는 데 사용 되 는데 이것 이 바로 CPU bound 에 속 하 는 프로그램 이다.
    CPU bound 프로그램 은 일반적으로 CPU 점용 률 이 상당히 높다.이 는 작업 자체 가 I/O 장치 에 접근 할 필요 가 없 기 때 문 일 수도 있 고,프로그램 이 다 중 스 레 드 로 이 루어 져 서 I/O 를 기다 리 는 시간 을 차단 한 것 일 수도 있 습 니 다.
    (2)IO 집약 형
    IO 집약 형 이란 시스템 의 CPU 성능 이 하 드 디스크,메모리 에 비해 훨씬 좋 은 것 을 말한다.이때 시스템 이 작 동 하고 대부분 CPU 가 I/O(하 드 디스크/메모리)의 읽 기/쓰기 작업 을 기다 리 고 있 는데 이때 CPU Loading 이 높 지 않다.
    I/O bound 프로그램 은 일반적으로 성능 한계 에 도 달 했 을 때 CPU 점용 률 이 여전히 낮다.이것 은 작업 자체 에 대량의 I/O 작업 이 필요 하기 때 문 일 수 있 으 며,pipeline 은 잘 하지 못 해서 프로세서 능력 을 충분히 이용 하지 못 했 기 때문이다.
    자,알 고 나 면 시작 하 겠 습 니 다.
    (3)먼저 기계 의 CPU 핵 수 를 보고 구체 적 인 파 라 메 터 를 설정 합 니 다.
    자기 기계 의 핵 수 를 스스로 측정 하 다.
    
    System.out.println(Runtime.getRuntime().availableProcessors());
    즉 CPU 핵 수=Runtime.getRuntime().availableProcessors()
    (4)오프라인 풀 처 리 를 분석 하 는 프로그램 이 CPU 밀집 형 인지 IO 밀집 형 인지
    CPU 밀집 형:corePoolSize=CPU 핵 수+1
    IO 밀집 형:corePoolSize=CPU 핵 수*2
    2,maximumPoolSize:최대 스 레 드 수
  • 스 레 드 수>=corePoolSize,그리고 작업 대기 열 이 가득 찼 을 때.스 레 드 탱크 는 작업 을 처리 하기 위해 새 스 레 드 를 만 들 것 입 니 다
  • 스 레 드 수=max PoolSize,그리고 작업 대기 열 이 가득 찼 을 때 스 레 드 탱크 는 작업 처 리 를 거부 하고 이상 을 던 집 니 다
  • 3.keepAliveTime:스 레 드 남 은 시간
  • 스 레 드 의 남 은 시간 이 keepAliveTime 에 이 르 렀 을 때 스 레 드 는 스 레 드 수량=corePoolSize 까지 종 료 됩 니 다
  • allowCoreThreadTimeout=true 라면 스 레 드 수량=0 까지.
  • 4.queueCapacity:작업 대기 열 용량(대기 열 차단)
    4
  • 핵심 스 레 드 수가 최대 에 이 르 렀 을 때 새 임 무 는 대기 열 에 놓 고 줄 을 서서 실 행 될 때 까지 기 다 립 니 다
  • 5.allowCoreThreadTimeout:핵심 스 레 드 시간 초과 허용
    6,rejected ExecutionHandler:작업 거부 프로세서
    두 가지 상황 은 임 무 를 처리 하 는 것 을 거절 할 것 이다.
  • 스 레 드 수가 max PoolSize 에 도 달 했 고 대기 열 이 가득 차 면 새로운 작업 을 거절 합 니 다
  • 4.567917.스 레 드 탱크 가 shutdown()으로 호출 되면 스 레 드 탱크 의 작업 이 끝 난 후에 shutdown 을 기다 릴 것 입 니 다.shutdown()과 스 레 드 풀 을 호출 하여 실제 shutdown 사이 에 작업 을 제출 하면 새 작업 을 거부 합 니 다스 레 드 탱크 는 rejected Execution Handler 를 호출 하여 이 임 무 를 처리 할 것 입 니 다.기본 값 이 AbortPolicy 인 것 을 설정 하지 않 으 면 이상 을 던 집 니 다.
    Thread PoolExecutor 는 임 무 를 거부 하 는 몇 가지 장면 을 전략 적 인 디자인 모델 로 처리 했다.
    이 몇 가지 전략 모델 은 모두 Rejected Execution Handler 인 터 페 이 스 를 실현 했다.
  • AbortPolicy 가 작업 을 버 리 고 실행 을 포기 할 때 이상 합 니 다.
  • CallerRunsPolicy 가 임 무 를 수행 합 니 다.
  • DiscardPolicy 무시,아무 일 도 일어나 지 않 습 니 다
  • DiscardOldestPolicy 는 대기 열 에서 가장 먼저 대기 열 에 들 어 가 는 작업(마지막 실행)을 차 냅 니 다
  • 3.매개 변 수 를 어떻게 설정 합 니까?
    기본 값:
    
    corePoolSize = 1
    maxPoolSize = Integer.MAX_VALUE
    queueCapacity = Integer.MAX_VALUE
    keepAliveTime = 60s
    allowCoreThreadTimeout = false
    rejectedExecutionHandler = AbortPolicy()
    어떻게 설정 하나 요?
    몇 개의 값 에 따라 결정 해 야 합 니까?
    tasks:초당 퀘 스 트 수,500~1000 으로 가정
    taskcost:모든 작업 에 시간 이 걸 리 며 0.1s 로 가정 합 니 다.
    responsetime:시스템 이 허용 하 는 최대 응답 시간 은 1s 로 가정 합 니 다.
    몇 가지 계산 을 하 다
    corePoolSize=1 초 에 몇 개의 스 레 드 처리 가 필요 합 니까?
    threadcount=tasks/(1/taskcost)=tasks*taskcout=(500~1000)*0.1=50~100 개의 스 레 드.
    core PoolSize 설정 은 50 이상 이 어야 합 니 다.
    8020 원칙 에 따 르 면 80%의 초당 퀘 스 트 수가 800 보다 적 으 면 core PoolSize 를 80 으로 설정 하면 된다.
    
    queueCapacity = (coreSizePool/taskcost)*responsetime
    계산 가능 queue Capacity=80/0.1*1=800.대기 열 에 있 는 스 레 드 는 1s 를 기다 릴 수 있 습 니 다.초과 한 스 레 드 를 실행 해 야 한 다 는 뜻 입 니 다.
    Integer.MAX 로 설정 할 수 없습니다.VALUE,이렇게 하면 대기 열 이 매우 클 것 입 니 다.스 레 드 수 는 core PoolSize 크기 만 유지 할 것 입 니 다.작업 이 급 격 히 증가 할 때 스 레 드 를 새로 열 어 실행 할 수 없 으 며 응답 시간 이 급 격 히 증가 할 것 입 니 다.
    max PoolSize 의 최대 스 레 드 수 는 생산 환경 에서 우 리 는 흔히 core PoolSize 처럼 설정 하면 처리 과정 에서 스 레 드 를 만 드 는 비용 을 줄 일 수 있 습 니 다.
    rejected Execution Handler:구체 적 인 상황 에 따라 임 무 는 중요 하지 않 고 버 릴 수 있 으 며 임 무 는 일부 버퍼 메커니즘 을 이용 하여 처리 해 야 합 니 다.
    keepAlive Time 과 allow CoreThreadTimeout 은 기본 값 으로 만족 합 니 다.
    이상 은 모두 이상 치 이 므 로 실제 상황 에서 기계 의 성능 에 따라 결정 해 야 한다.최대 스 레 드 에 도달 하지 못 한 경우 기계 cpu load 가 가득 찼 다 면 하드웨어 업그레이드 와 최적화 코드 를 통 해 taskcost 를 낮 춰 처리 해 야 합 니 다.
    다음은 제 스 레 드 탱크 설정 입 니 다.
    
    @Configuration
    public class ConcurrentThreadGlobalConfig {
        @Bean
        public ThreadPoolTaskExecutor defaultThreadPool() {
            ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
            //      
            executor.setCorePoolSize(65);
            //       
            executor.setMaxPoolSize(65);
            //        
            executor.setQueueCapacity(650);
            //      
            executor.setThreadNamePrefix("DefaultThreadPool_");
            //rejection-policy: pool    max size   ,       
            //CALLER_RUNS:          ,              
            //   task     
            executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
            //            
            executor.setKeepAliveSeconds(60);
            //  
            executor.initialize();
            return executor;
        }
    }
    
    4.스 레 드 탱크 대기 열의 선택
    workQueue-스 레 드 수가 핵심 스 레 드 수 를 초과 할 때 작업 의 대기 열 을 저장 합 니 다.주로 3 가지 유형의 BlockingQueue 를 선택 할 수 있 습 니 다.무한 대기 열,경계 대기 열 과 동기 화 전환 이 있 습 니 다.매개 변수 에서 볼 수 있 듯 이 이 대기 열 은 Runnable 인 터 페 이 스 를 실현 하 는 작업 만 저장 합 니 다.
    새 작업 이 들 어 갈 때 스 레 드 탱크 의 실행 전략 을 다시 한 번 반복 합 니 다.
  • 실행 중인 스 레 드 가 corePoolSize 보다 작 으 면 스 레 드 탱크 는 새로운 스 레 드 를 만 듭 니 다
  • corePoolSize 보다 크 고 작업 대기 열 이 채 워 지지 않 으 면 전체 작업 을 대기 열 에 넣 습 니 다
  • corePoolSize 보다 크 고 작업 대기 열 이 가득 찼 을 때 maximumPoolSize 보다 작 을 때 새 스 레 드 를 만들어 작업 을 수행 합 니 다
  • maximum PoolSize 보다 크 면 handler 전략 에 따라 스 레 드 를 처리 합 니 다
  • 1.무한 대기 열
    대기 열 크기 는 제한 이 없습니다.항상 사용 되 는 링크 드 BlockingQueue 입 니 다.이 대기 열 을 차단 대기 열 로 사용 할 때 특히 주의해 야 합 니 다.작업 시간 이 오래 걸 릴 때 대량의 새로운 작업 이 대기 열 에 쌓 여 결국 OOM 을 초래 할 수 있 습 니 다.
    코드 를 읽 어 보 니 Executors.new Fixed ThreadPool 은 링크 드 BlockingQueue 를 사 용 했 습 니 다.블 로 거 가 밟 은 것 은 바로 이 구 덩이 였 습 니 다.QPS 가 높 고 데 이 터 를 많이 보 내 며 대량의 작업 이 이 무한 링크 드 BlockingQueue 에 추가 되 어 cpu 와 메모리 가 급증 하여 서버 가 끊 겼 습 니 다.
    물론 이 대기 열 은 maximum PoolSize 의 값 도 유효 하지 않 습 니 다.
    모든 작업 이 다른 작업 에 완전히 독립 되 었 을 때,즉 작업 수행 이 서로 영향 을 주지 않 을 때,무한 대기 열 을 사용 하 는 데 적합 합 니 다.예 를 들 어 웹 페이지 서버 에서.
    이 줄 은 과도 돌발 요 구 를 처리 하 는 데 사용 할 수 있 습 니 다.명령 이 대기 열 에서 처리 할 수 있 는 평균 수 를 초과 하여 연속 으로 도착 할 때 이 전략 은 무한 스 레 드 가 증가 할 가능성 을 허용 합 니 다.
    2.유 계 대열
    제 한 된 maximum PoolSizes 를 사용 할 때 경계 대기 열 은 자원 소 모 를 방지 하 는 데 도움 이 되 지만 조정 과 통제 가 어 려 울 수 있 습 니 다.
    자주 사용 되 는 두 가지 유형 이 있 는데 하 나 는 FIFO 원칙 을 따 르 는 대기 열,예 를 들 어 Array BlockingQueue 이 고 다른 하 나 는 Priority BlockingQueue 와 같은 우선 순위 대기 열 입 니 다.
    Priority BlockingQueue 의 우선 순 위 는 작업 의 Comparator 에 의 해 결 정 됩 니 다.
    경계 대기 열 을 사용 할 때 대기 열 크기 는 스 레 드 탱크 크기 와 서로 어 울 려 야 합 니 다.스 레 드 탱크 가 비교적 작 을 때 메모리 소 모 를 줄 이 고 cpu 사용률 과 문맥 전환 을 낮 출 수 있 으 나 시스템 스루풋 을 제한 할 수 있 습 니 다.
    3.동기 전환 대기 열
    대기 열 에서 작업 을 기다 리 지 않 고 작업 스 레 드 에 직접 넘 기 려 면 SynchronousQueue 를 대기 열 로 사용 할 수 있 습 니 다.
    SynchronousQueue 는 진정한 대기 열 이 아니 라 스 레 드 간 이 양 메커니즘 입 니 다.하나의 요 소 를 SynchronousQueue 에 넣 으 려 면 다른 스 레 드 가 이 요 소 를 받 기 를 기다 리 고 있어 야 합 니 다.
    무 계 스 레 드 탱크 나 포화 정책 을 사용 할 때 만 이 대기 열 을 사용 하 는 것 을 권장 합 니 다.
    이상 은 개인 적 인 경험 이 므 로 여러분 에 게 참고 가 되 기 를 바 랍 니 다.여러분 들 도 저 희 를 많이 응원 해 주시 기 바 랍 니 다.

    좋은 웹페이지 즐겨찾기