java 스레드 풀 분석

도는 스스로
http://www.cnblogs.com/evilrogue/archive/2013/01/29/2881430.html


JAVA스레드 풀 분석 및 사용
1. 서문
합리적 이용 스레드 풀 가져올 수 있는 좋은 세 개. 첫째: 자원 소비를 줄이다. 통해 이미 반복 이용하여 만든 스레드 스레드 수 있다, 없애버린다 인한 소모. 둘째: 응답 속도를 높이다. 이 임무는 도착했을 때 임무를 필요 스레드 수 있을 때까지 만들 수 즉시 집행하다. 셋째: 스레드의 관리 기능 향상. 스레드 것은 드물다 자원 경우 제한 없고 만들 수 있을 뿐만 아니라 시스템 리소스 소모, 또 내리기 시스템 안정성, 사용 명세서 풀 을 통일 분배 수 조정하여 개량하다 및 모니터링. 근데 왜 그렇게 합리적인 이용 스레드 풀 반드시 그 원리 손금 보듯이 훤히 알다.

2. 스레드 사용할
스레드 지 만들기

우리 통과할 수 있다 ThreadPoolExecutor 만드십시오 스레드 풀.

new  ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, milliseconds,runnableTaskQueue, handler);
만듭니다. 스레드 수영장 수요 입력 몇 매개 변수:

corePoolSize(스레드 풀 기본 크기): 걸로 하나 까지 제출 작업 명세서 풀 때 스레드 스레드 될 지 만듭니다. 자, 임무를 집행하다, 설령 다른 빈 기본 스레드 수 있는 새로운 임무를 수행하는 도 만들 때까지 스레드, 필요 수행한 임무는 몇 크다 스레드 풀 기본 크기 때 다시 만듭니다.만약 호출 거야 스레드 연못prestartAllCoreThreads방법, 스레드 풀 줄 미리 만들기 결코 모든 기본 스레드 작동.
runnableTaskQueue(작업 대기행렬): 저장 기다리다 실행할 임무를 체증 큐.선택할 수 있는 아래의 몇 체증 대기 행렬.
ArrayBlockingQueue: 是一个基于数组结构的有界阻塞队列, 此队列按 FIFO(先进先出)原则对元素进行排序.
LinkedBlockingQueue: 一个基于链表结构的阻塞队列, 此队列按FIFO (先进先出) 排序元素, 吞吐量通常要高于ArrayBlockingQueue. 静态工厂方法Executors.newFixedThreadPool()이 큐 사용.
SynchronousQueue: 一个不存储元素的阻塞队列. 每个插入操作必须等到另一个线程调用移除操作, 否则插入操作一直处于阻塞状态, 吞吐量通常要高于LinkedBlockingQueue, 静态工厂方法Executors.newCachedThreadPool이 큐 사용.
PriorityBlockingQueue: 一个具有优先级的无限阻塞队列.
maximumPoolSize(최대 크기): 스레드 스레드 연못 지 마음대로 만들기 최대 스레드 수 있다.만약 대기열 가득 또한 이미 만든 스레드 수 < 최대 스레드 스레드 수 는 연못 다시 새 스레드 임무를 집행하다.주목할 것은, 만약 사용할 无界 작업 대기열 이 인자 뭐 효과.
ThreadFactory: 用于设置创建线程的工厂, 可以通过线程工厂给每个创建出来的线程设置更有意义的名字.
RejectedExecutionHandler(포화 정책): 이 큐 및 스레드 지 다 가득 설명 스레드 풀 포화상태다 그렇게 반드시 한 가지 정책을 취하다 처리 제출한 새로운 임무.이 정책을 기본 상황 은 AbortPolicy 대해 새로운 임무를 때 넉살좋게 처리할 수 없습니다.다음은 JDK1.5 제공하는 네 가지 정책.
AbortPolicy: 직접 방매하다 이상.
CallerRunsPolicy: 只用调用者所在线程来运行任务.
DiscardOldestPolicy: 丢弃队列里最近的一个任务, 并执行当前任务.
DiscardPolicy: 不处理, 丢弃掉.
물론 따라 유지될 수 응용 장면 필요하다.RejectedExecutionHandler인터페이스 정의 정책.만약 기록 로그 또는 영구적으로 만들 수 처리 작업.
keepAliveTime(스레드 작동 유지 시간): 스레드 스레드 한가할 지 일 후 생존 시간을 지키다.그래서 만약 임무를 많은 또한 모든 작업 시간이 비교적 짧은 수 조사 큰 이 시간 을 높이 스레드의 사용량.
TimeUnit (스레드 작동 유지 시간 단위): 추가 부서에는 날 (DAYS), 시간 (HOURS) 분 (MINUTES) 을 초 (MILLISECONDS) 을 초 (MICROSECONDS, 1000분의 1 초) 과 밀리마이크로초 (NANOSECONDS, 1000분의 1 초).
향해 스레드 풀 커밋 작업

우리 사용할 수 execute 커밋 작업 하지만 execute 방법이 복귀 값, 그래서 판단할 수 있는지 스레드 풀 실행 성공적으로 임무를 받았다.이하 코드 입력 임무를 알 수 execute 방법을 통해 한 Runnable 같은 인스턴스.

threadsPool.execute(new Runnable() {
            @Override
            public void run() {
                // TODO Auto-generated method stub
            }
        });
우리도 사용할 수 submit 방법으로 커밋 작업 그것을 어떻게 반환하였습니다 future, 그럼 우리 인터넷을 통하여 이 future 판단해 임무를 집행하다 성공 여부, future 있는 get 방법을 통해 온 가져오기 복귀 값, get 방법이 있을 때까지 막힌다 사는 임무를 위해 사용get(long timeout, TimeUnit unit)방법 은 어떻게 체증 한동안 후 즉시 복귀, 이때 수도 없이 다 임무를 집행하다.

Future<Object> future = executor.submit(harReturnValuetask);
try {
     Object s = future.get();
} catch (InterruptedException e) {
    // 예외 처리 중단
} catch (ExecutionException e) {
    // 실행 태스크 이상 처리할 수 없습니다.
} finally {
    // 닫기 스레드 풀
    executor.shutdown();
}
스레드 지 닫기

우리 가 호출 스레드 지 shutdown 또는 shutdownNow 방법을 통해 온 지 닫기 스레드 그것들은 원리는 사이를 옮겨다니기 스레드 연못 속의 작업 개체, 그리고 하나하나 호출 스레드의 interrupt 방법으로 중단 명세서 때문에 못 응답 중단 임무는 아마 영원히 못 결국 하다. 하지만 그들은 일정한 차이가 존재하고, shutdownNow 먼저 스레드 풀 상태 설정 되어 스톱, 그리고 시도 중지 모든 실행 중 또는 잠시 임무를 스레드 하 고 복귀 대기 작업 목록, 때문에 shutdown 그냥 스레드 풀 상태 설정 될 것이다 SHUTDOWN 모양의 상태, 그리고 중단 없이 작업의 모든 스레드의 실행 중.

그냥 호출 이 두 닫기 방법 중 하나 isShutdown 방법을 곧 복귀 true. 이 모든 작업 다 닫힌 후 비로소 표시 스레드 풀 닫기 성공, 이때 호출 isTerminaed 방법 어떻게 복귀 true. 왜 우리는 반드시 호출 어떤 방법으로 닫기 스레드 지 행사장에 제출 다 스레드 풀 임무를 특성 결정, 보통 호출 shutdown 온 닫기 스레드 연못, 만약 임무를 반드시 실행할 수 shutdownNow 다 않으면 호출.

3. 스레드 풀 분석
흐름 해석: 스레드 수영장의 주요 업무 절차 下图 같다.:



은 콘서트 무대 오른 우리 볼 수 있다 고 제출한 새로운 임무를 다 스레드 스레드 못 풀 때 처리 절차 다음과 같다:

일단 기본 스레드 스레드 지 여부를 판단할 연못 가득 찼습니까? 안 가득 만듭니다. 작업 개체 온 임무를 집행하다.가득 않으면 진입 다음 흐름.
다음 스레드 지 여부 판단 작업 대기행렬 가득 찼습니까? 안 가득 는 새 커밋 작업 저장 작업 대기열 있다.가득 않으면 진입 다음 흐름.
마지막 스레드 스레드 지 여부 판단 온 지 이미 가득? 안 가득 않으면 새 작업 개체 온 임무를 집행하다, 가득 은 넘겨 처리할 이 임무를 포화 정책.
원본 코드 분석.위의 공정 분석 우리를 매우 직관적 대해서 스레드 풀 작업 원리, 우리 다시 통해 소스 코드 와서 좀 어떻게 실현합니까?스레드 풀 작업 방법은 다음과 같다:

public void execute(Runnable command) {
    if (command == null)
       throw new NullPointerException();
    //만약 스레드 수 < 기본 스레드 수 없는 만들기 스레드 결코 현재 임무를 집행하다
    if (poolSize >= corePoolSize || !addIfUnderCorePoolSize(command)) {
    //만약 스레드 수 다음보다 크거나 같음 기본 스레드 수 또는 스레드 생성 실패 는 현재 작업 후 작업 대기행렬 중.
        if (runState == RUNNING && workQueue.offer(command)) {
            if (runState != RUNNING || poolSize == 0)
                      ensureQueuedTaskHandled(command);
        }
    //만약 스레드 풀 안 에 실행 중 또는 작업 대기행렬 넣고 수 있으며, 현재 스레드 스레드 수 있는 최대 허용 수량이 적다,
은 만듭니다. 스레드 임무를 집행하다.
        else if (!addIfUnderMaximumPoolSize(command))
        //투매하다RejectedExecutionException이상
            reject(command); // is shutdown or saturated
    }
}
작업 명세서.스레드 스레드 연못 만들 때 것이다 스레드 패키지 된 작업 개체 Worker, Worker 다 임무 수행 후 또 무한 사이클 작업 대기행렬 안의 작업 가져오기 와 집행하다.우리 는 Worker 수 있는 방법을 보면 이 안에 run:

public void run() {
     try {
           Runnable task = firstTask;
           firstTask = null;
            while (task != null || (task = getTask()) != null) {
                    runTask(task);
                    task = null;
            }
      } finally {
             workerDone(this);
      }
}
4. 합리적인 배치 스레드 풀
하려면 합리적인 배치 스레드 지 반드시 임무를 특성 분석 우선 쌀값은 이하 몇 관점에서 분석한:

임무를 성질: CPU 집약형 임무를 IO 집약형 작업 및 혼합형 임무.
작업 우선 순위: 높고 낮은 중화.
임무를 집행하다 길고 짧은 시간: 중화.
임무를 의존성: 혹시 의존 시스템 자원을 다른 예를 데이터베이스 연결.
임무를 성질 다른 임무를 다른 규모의 스레드 못 쓸 수 따로따로 처리하다. CPU 집약형 작업 설정 가능한 작은 스레드, 만약 설정 Ncpu+1 개 스레드의 스레드 풀. IO 집약형 작업 은 스레드 결코 계속 작업 때문에 은 설정 가능한 한 많은 스레드. 예 2*Ncpu. 혼합형 임무를 나누기 는 수 있다면, 그 분할 분장했다 CPU 집약형 작업 및 한 IO 집약형 임무를 하면 이 두 작업 시간 차이는 거 너무 커서 그렇게 분해 후 실행할 탄토하다 속도 보다 직렬 실행할 탄토하다 율. 만약 이 두 임무를 집행하다 시간이 너무 커서 은 필요 진행 분해. 우리 통과할 수 있다Runtime.getRuntime().availableProcessors()방법을 얻게 현재 설비 CPU 개수.

우선 순위 다른 작업 대기행렬 우선순위 사용할 수 있습니다.PriorityBlockingQueue할게.그것은 수 있도록 우선 순위 높은 임무를 집행하다 먼저 받다, 주의를 필요로 하는 것은 만약 항상 우선 순위 높은 임무를 제출 까지 대기 행렬 속에서 그럼 우선 순위 낮음 임무는 아마 영원히 못 실행.

실행 시간 다른 임무가 맡길 수 다른 규모의 스레드 지 와 처리 혹은 우선 대기 행렬 도 사용할 수 있도록 먼저 실행 시간 짧은 임무를 집행하다.

데이터베이스 연결 작업 의존 지 때문에 스레드 SQL 후 제출 더 기다리다 데이터베이스 복귀 결과, 만약 기다리는 오래 될수록 CPU 여유가 있으면 더 긴 스레드 수 있을 만큼 설정 커질수록 그래야 더 이용 CPU.

건의를 것인지에 경계 행렬, 경계 큐 시스템 안정화 및 경보 능력 있는 것으로 필요에 따라 큰 수 신설 좀 예를 수천. 한 번 우리 팀 사용할 배경 작업 명세서 풀 행렬, 스레드 풀 全满, 끊임없이 버린 풀 임무를 이상한 사람 것을 통해 데이터베이스 나타난 문제 때문에 실행 SQL 더 매우 느리다 때문에 배경 작업 명세서 못에 임무를 다 필요 향해 데이터베이스 쿼리 및 산입 데이터, 그래서 스레드 연못 속의 작업 개체 모두 체증 수 있는 - 程池里 임무. 만약 그때 우리 설정 된다 无界 행렬, 스레드 풀 행렬 곧 날이 갈수록 수도 배불러 가득 메모리 줄여 전체 시스템 사용 불가능한 때문에 그냥 배경 작업 문제의. 물론 우리 시스템 모든 임무는 쓰는 따로 서버 배치, 때문에 우리가 사용하는 다른 규모의 스레드 못 뛰어 다른 유형의 임무, 근데 이런 문제를 때도 영향을 끼칠 다른 작업.

5. 스레드 풀 CCTV
통해 스레드 풀 제공하는 인자 대한 모니터링.스레드 연못 안의 어떤 속성 모니터링할 스레드 풀 때 사용할 수 있습니다.

taskCount: 线程池需要执行的任务数量.
completedTaskCount: 线程池在运行过程中已完成的任务数量. 小于或等于taskCount.
largestPoolSize: 线程池曾经创建过的最大线程数量. 通过这个数据可以知道线程池是否满过. 같다等于线程池的最大大小, 则表示线程池曾经满了.
지 getPoolSize: 스레드 스레드 수량.만약 스레드 풀 안 되거나 말을 못 안의 스레드 안 자동 정리하기 때문에 이 크기 마리 (안 + getActiveCount: 가져오는 중 활동 스레드 수.
통해 확장 스레드 풀 대한 모니터링. 상속 스레드 스레드 지 못 하 고 재작성 beforeExecute 통해 afterExecute 및 terminated 방법 을 우리 가 임무 수행 전에 실시 후 닫기 전에 및 스레드 못 하는 게 좀 있어서. 만약 모니터링 작업 평균 실행 시간, 최대 실행 시간 및 최소 실행 시간 등. 이 몇 가지 방법 - 거리 못에 빈 방법. 如:

protected void beforeExecute(Thread t, Runnable r) { }
6. 참고 자료
자바 동시성 프로그래밍 실전.
JDK1.6 소스


전재 ": ;utm_medium=related_content_link&utm_campaign=relatedContent_articles_clk

글쓴이 Yeo 작성일 2015-01-21 01:40