자바 구문 분석 스레드 풀

스레드 풀

풀 개요 스레드

  • 스레드 풀은 무엇입니까

  • 왜 스레드 풀을 사용

  • 스레드 풀 활용

    • 첫째, 자원 소비를 줄일 수 있습니다. 스레드를 재사용함으로써 소비에 의한 스레드 생성과 파괴를 줄이기 위해 생성되었다.

    • 둘째 : 응답 속도를 향상시킬 수있다. 미션이 도착하면 작업은 스레드 생성 즉시 구현 될 수있을 때까지 기다릴 필요가 없습니다 수 있습니다.

    • 셋째 : 스레드의 관리 성을 향상시킬 수 있습니다. 무제한 생성이뿐만 아니라 시스템 리소스를 소모뿐만 아니라 유통, 튜닝 및 모니터링을 통합 할 수있는 스레드 풀을 사용하여 시스템의 안정성을 줄일 경우 스레드는, 희소 한 자원이다. 하지만 스레드 풀의 합리적인 사용이 원칙을 잘 알고 있어야합니다.

스레드 풀 스레드를 생성하고 작업을 제출

소스 구문 분석 스레드 풀

매개 변수는 알고있다

  1. corePoolSize를 : 스레드 풀에 작업을 제출할 때 작업의 수가 스레드보다 큰 수행해야 할 때까지 스레드 풀의 기본 크기는, 스레드 풀, 새 작업을 수행 할 수있는 다른 무료 기본 스레드가 스레드를 만들 수있을 것입니다 경우에도 작업을 수행 할 스레드를 생성합니다 만든 풀은 더 이상 기본 크기 없을 때. 당신이 방법 prestartAllCoreThreads 스레드 풀을 호출하면 스레드 풀은 사전에 만들어지고 모든 기본 스레드를 시작합니다.

  2. runnableTaskQueue : 작업 열 저장이 큐 대기를 차단하는 작업이 실행되는 것이다. 다음 블록 큐를 선택할 수 있습니다.

  • ArrayBlockingQueue 등 : 배열 기반 큐를 구성이 큐 (First In First Out) 방식으로 FIFO 원리 정렬 요소를 차단 유계.

  • LinkedBlockingQueue 등은 : 보통 높은 소정 ArrayBlockingQueue를보다 큐 FIFO (선입) 조합 요소에있어서,리스트 구조를 기반으로 큐를 차단. 정적 공장 메소드 Executors.newFixedThreadPool ()이 큐를 이용한다.

  • SynchronousQueue는 : 블로킹 큐 요소는 저장되지 않는다. 다른 스레드가 제거 작업 호출, 또는 삽입 작업은 일반적으로 높은 LinkedBlockingQueue 등보다 정적 팩토리 메소드이 큐를 사용 Executors.newCachedThreadPool 처리량이 차단 된 상태로 될 때까지 각 삽입 작업은 기다려야합니다.

  • 인 PriorityBlockingQueue : 우선 순위 무한 블록 큐.

  1. maximumPoolSize를 : 스레드 풀의 최대 크기는 스레드 풀은 스레드의 최대 수를 만들 수 있습니다. 큐가 적은 스레드의 최대 수보다 생성 된 스레드의 수는 전체이며, 경우, 스레드 풀은 작업을 수행 할 수있는 새로운 스레드를 다시 만듭니다. 그것은 당신이 아무런 영향이 매개 변수 큐 무제한의 작업을 사용하는 경우 있음을 주목할 필요가있다.

  2. ThreadFactory를이 : 스레드를 만들 수있는 공장을 설정하는 데 사용, 도움은 스레드 이름, 디버그 및 위치 문제에서 스레드 공장에서 만든 각 매우 의미있는 설정할 수 있습니다.

  3. RejectedExecutionHandler (포화 정책) : 큐와 스레드 풀 스레드 풀은 포화되어 있음을 나타냅니다 가득 때, 새 작업 제출을 처리하기위한 전략을 채택해야합니다. 기본적으로이 전략은 AbortPolicy, 그것은 새 작업을 처리 할 때 예외를 던질 수 없다고 말했다.

  • CallerRunsPolicy : 경우에만 호출 스레드가 작업을 실행합니다.

  • 의 DiscardOldestPolicy : 폐기 큐 최근 작업과 현재 작업을 실행합니다.

  • DiscardPolicy : 없음 처리, 폐기.

  • 물론, 당신은 응용 프로그램 시나리오에 따라 사용자 정의 정책 RejectedExecutionHandler 인터페이스를 구현해야 할 수 있습니다. 로깅 또는 지속성 작업을 처리 할 수있는 그런.

  1. 이 KeepAliveTime : 살아있는 시간을 유지하기 위해 유휴 작업자 스레드 풀 후, 유지 시간 스레드 활동. 그래서 작업을 많이하고, 각 작업 실행 시간이 비교적 짧은 경우, 그것은이 시간을 돌려 스레드의 활용을 향상시킬 수 있습니다.

  2. TimeUnit와 : 체류 시간 스레드 활성 유닛, 1 일 단위로 선택적으로 (일), H (시간), 최소 시간 (분) MS 시간 (밀리 초), 마이크로 (마이크로 초 천분 MS) 및 NS ( 나노 초, 천분의 마이크로 초).

  3. 클래스의 다른 속성


    // 线程池的控制状态:用来表示线程池的运行状态(整型的高3位)和运行的worker数量(低29位)
    private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
    // 29位的偏移量
    private static final int COUNT_BITS = Integer.SIZE - 3;
    // 最大容量(2^29 - 1)
    private static final int CAPACITY   = (1 << COUNT_BITS) - 1;

    // runState is stored in the high-order bits
    // 线程运行状态,总共有5个状态,需要3位来表示(所以偏移量的29 = 32 - 3)
   /**
    * RUNNING    :    接受新任务并且处理已经进入阻塞队列的任务
    * SHUTDOWN    :    不接受新任务,但是处理已经进入阻塞队列的任务
    * STOP        :    不接受新任务,不处理已经进入阻塞队列的任务并且中断正在运行的任务
    * TIDYING    :    所有的任务都已经终止,workerCount为0, 线程转化为TIDYING状态并且调用terminated钩子函数
    * TERMINATED:    terminated钩子函数已经运行完成
    **/
    private static final int RUNNING    = -1 << COUNT_BITS;
    private static final int SHUTDOWN   =  0 << COUNT_BITS;
    private static final int STOP       =  1 << COUNT_BITS;
    private static final int TIDYING    =  2 << COUNT_BITS;
    private static final int TERMINATED =  3 << COUNT_BITS;
    // 阻塞队列
    private final BlockingQueue<Runnable> workQueue;
    // 可重入锁
    private final ReentrantLock mainLock = new ReentrantLock();
    // 存放工作线程集合
    private final HashSet<Worker> workers = new HashSet<Worker>();
    // 终止条件
    private final Condition termination = mainLock.newCondition();
    // 最大线程池容量
    private int largestPoolSize;
    // 已完成任务数量
    private long completedTaskCount;
    // 线程工厂
    private volatile ThreadFactory threadFactory;
    // 拒绝执行处理器
    private volatile RejectedExecutionHandler handler;
    // 线程等待运行时间
    private volatile long keepAliveTime;
    // 是否运行核心线程超时
    private volatile boolean allowCoreThreadTimeOut;
    // 核心池的大小
    private volatile int corePoolSize;
    // 最大线程池大小
    private volatile int maximumPoolSize;
    // 默认拒绝执行处理器
    private static final RejectedExecutionHandler defaultHandler =
        new AbortPolicy();

생성자

    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler) {
        if (corePoolSize < 0 ||                                                // 核心大小不能小于0
            maximumPoolSize <= 0 ||                                            // 线程池的初始最大容量不能小于0
            maximumPoolSize < corePoolSize ||                                // 初始最大容量不能小于核心大小
            keepAliveTime < 0)                                                // keepAliveTime不能小于0
            throw new IllegalArgumentException();                                
        if (workQueue == null || threadFactory == null || handler == null)
            throw new NullPointerException();
        // 初始化相应的域
        this.corePoolSize = corePoolSize;
        this.maximumPoolSize = maximumPoolSize;
        this.workQueue = workQueue;
        this.keepAliveTime = unit.toNanos(keepAliveTime);
        this.threadFactory = threadFactory;
        this.handler = handler;
    }

작업 제출

/*
* 进行下面三步
*
* 1. 如果运行的线程小于corePoolSize,则尝试使用用户定义的Runnalbe对象创建一个新的线程
*     调用addWorker函数会原子性的检查runState和workCount,通过返回false来防止在不应
*     该添加线程时添加了线程
* 2. 如果一个任务能够成功入队列,在添加一个线城时仍需要进行双重检查(因为在前一次检查后
*     该线程死亡了),或者当进入到此方法时,线程池已经shutdown了,所以需要再次检查状态,
*    若有必要,当停止时还需要回滚入队列操作,或者当线程池没有线程时需要创建一个新线程
* 3. 如果无法入队列,那么需要增加一个新线程,如果此操作失败,那么就意味着线程池已经shut
*     down或者已经饱和了,所以拒绝任务
*/
public void execute(Runnable command) {
    if (command == null)
        throw new NullPointerException();
    // 获取线程池控制状态
    int c = ctl.get();
    if (workerCountOf(c) < corePoolSize) { // worker数量小于corePoolSize
        if (addWorker(command, true)) // 添加worker
            // 成功则返回
            return;
        // 不成功则再次获取线程池控制状态
        c = ctl.get();
    }
    // 线程池处于RUNNING状态,将用户自定义的Runnable对象添加进workQueue队列
    if (isRunning(c) && workQueue.offer(command)) { 
        // 再次检查,获取线程池控制状态
        int recheck = ctl.get();
        // 线程池不处于RUNNING状态,将自定义任务从workQueue队列中移除
        if (! isRunning(recheck) && remove(command)) 
            // 拒绝执行命令
            reject(command);
        else if (workerCountOf(recheck) == 0) // worker数量等于0
            // 添加worker
            addWorker(null, false);
    }
    else if (!addWorker(command, false)) // 添加worker失败
        // 拒绝执行命令
        reject(command);
}

addWorker

  1. 원자 workerCount 증가.

  2. 사용자는 노동자, 노동자를 포장하는 작업을 주어이 컬렉션 근로자를 추가합니다.

  3. 시작 작업자 스레드에 대응하고, 스레드는 노동자의 실행 방법을 실행하기 시작합니다.

  4. 롤백 작업 근로자를 작성, 작업자는 곧 노동자의 세트로부터 삭제하고, 원자는 workerCount을 줄일 수 있습니다.

private boolean addWorker(Runnable firstTask, boolean core) {
    retry:
    for (;;) { // 外层无限循环
        // 获取线程池控制状态
        int c = ctl.get();
        // 获取状态
        int rs = runStateOf(c);

        // Check if queue empty only if necessary.
        if (rs >= SHUTDOWN &&            // 状态大于等于SHUTDOWN,初始的ctl为RUNNING,小于SHUTDOWN
            ! (rs == SHUTDOWN &&        // 状态为SHUTDOWN
               firstTask == null &&        // 第一个任务为null
               ! workQueue.isEmpty()))     // worker队列不为空
            // 返回
            return false;

        for (;;) {
            // worker数量
            int wc = workerCountOf(c);
            if (wc >= CAPACITY ||                                // worker数量大于等于最大容量
                wc >= (core ? corePoolSize : maximumPoolSize))    // worker数量大于等于核心线程池大小或者最大线程池大小
                return false;
            if (compareAndIncrementWorkerCount(c))                 // 比较并增加worker的数量
                // 跳出外层循环
                break retry;
            // 获取线程池控制状态
            c = ctl.get();  // Re-read ctl
            if (runStateOf(c) != rs) // 此次的状态与上次获取的状态不相同
                // 跳过剩余部分,继续循环
                continue retry;
            // else CAS failed due to workerCount change; retry inner loop
        }
    }

    // worker开始标识
    boolean workerStarted = false;
    // worker被添加标识
    boolean workerAdded = false;
    // 
    Worker w = null;
    try {
        // 初始化worker
        w = new Worker(firstTask);
        // 获取worker对应的线程
        final Thread t = w.thread;
        if (t != null) { // 线程不为null
            // 线程池锁
            final ReentrantLock mainLock = this.mainLock;
            // 获取锁
            mainLock.lock();
            try {
                // Recheck while holding lock.
                // Back out on ThreadFactory failure or if
                // shut down before lock acquired.
                // 线程池的运行状态
                int rs = runStateOf(ctl.get());

                if (rs < SHUTDOWN ||                                    // 小于SHUTDOWN
                    (rs == SHUTDOWN && firstTask == null)) {            // 等于SHUTDOWN并且firstTask为null
                    if (t.isAlive()) // precheck that t is startable    // 线程刚添加进来,还未启动就存活
                        // 抛出线程状态异常
                        throw new IllegalThreadStateException();
                    // 将worker添加到worker集合
                    workers.add(w);
                    // 获取worker集合的大小
                    int s = workers.size();
                    if (s > largestPoolSize) // 队列大小大于largestPoolSize
                        // 重新设置largestPoolSize
                        largestPoolSize = s;
                    // 设置worker已被添加标识
                    workerAdded = true;
                }
            } finally {
                // 释放锁
                mainLock.unlock();
            }
            if (workerAdded) { // worker被添加
                // 开始执行worker的run方法
                t.start();
                // 设置worker已开始标识
                workerStarted = true;
            }
        }
    } finally {
        if (! workerStarted) // worker没有开始
            // 添加worker失败
            addWorkerFailed(w);
    }
    return workerStarted;
}

사명

runWorker 기능은 실제로 주어진 작업을 (즉, 사용자가 실행 방법 재기록를 호출)을 수행하며, 큐가 비어있는 장애물 (즉, 완료된 작업)이 될 때까지 주어진 작업의 완료 후, 태스크는 큐를 차단하는 취할 것입니다. 주어진 작업을 수행하는 동안, 일부 사용자 정의 논리를 할 수있는 후크 기능을 사용하여, 후크 함수를 호출합니다. runWorker에서 후크 함수를 getTask 기능과 processWorkerExit를 호출합니다

final void runWorker(Worker w) {
    // 获取当前线程
    Thread wt = Thread.currentThread();
    // 获取w的firstTask
    Runnable task = w.firstTask;
    // 设置w的firstTask为null
    w.firstTask = null;
    // 释放锁(设置state为0,允许中断)
    w.unlock(); // allow interrupts
    boolean completedAbruptly = true;
    try {
        while (task != null || (task = getTask()) != null) { // 任务不为null或者阻塞队列还存在任务
            // 获取锁
            w.lock();
            // If pool is stopping, ensure thread is interrupted;
            // if not, ensure thread is not interrupted.  This
            // requires a recheck in second case to deal with
            // shutdownNow race while clearing interrupt
            if ((runStateAtLeast(ctl.get(), STOP) ||    // 线程池的运行状态至少应该高于STOP
                 (Thread.interrupted() &&                // 线程被中断
                  runStateAtLeast(ctl.get(), STOP))) &&    // 再次检查,线程池的运行状态至少应该高于STOP
                !wt.isInterrupted())                    // wt线程(当前线程)没有被中断
                wt.interrupt();                            // 中断wt线程(当前线程)
            try {
                // 在执行之前调用钩子函数
                beforeExecute(wt, task);
                Throwable thrown = null;
                try {
                    // 运行给定的任务
                    task.run();
                } catch (RuntimeException x) {
                    thrown = x; throw x;
                } catch (Error x) {
                    thrown = x; throw x;
                } catch (Throwable x) {
                    thrown = x; throw new Error(x);
                } finally {
                    // 执行完后调用钩子函数
                    afterExecute(task, thrown);
                }
            } finally {
                task = null;
                // 增加给worker完成的任务数量
                w.completedTasks++;
                // 释放锁
                w.unlock();
            }
        }
        completedAbruptly = false;
    } finally {
        // 处理完成后,调用钩子函数
        processWorkerExit(w, completedAbruptly);
    }
}

큐가 차단되기 때문에,이 기능은, 큐 블로킹 workerQueue의 Runnable 객체를 얻기 위해 사용되며, 이는 제한 시간 (폴링) 및 무한 대기 (인출)을 기다린다. 이 함수와 같은 스레드 풀 감지되면 동작 종료, shutdownNow의 기능에 응답 STOP 상태 SHUTDOWN에 null를 리턴되고 Runnalbe를 반환하지 않는 객체 큐 막았다.

    private Runnable getTask() {
        boolean timedOut = false; // Did the last poll() time out?

        for (;;) { // 无限循环,确保操作成功
            // 获取线程池控制状态
            int c = ctl.get();
            // 运行的状态
            int rs = runStateOf(c);

            // Check if queue empty only if necessary.
            if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) { // 大于等于SHUTDOWN(表示调用了shutDown)并且(大于等于STOP(调用了shutDownNow)或者worker阻塞队列为空)
                // 减少worker的数量
                decrementWorkerCount();
                // 返回null,不执行任务
                return null;
            }
            // 获取worker数量
            int wc = workerCountOf(c);

            // Are workers subject to culling?
            boolean timed = allowCoreThreadTimeOut || wc > corePoolSize; // 是否允许coreThread超时或者workerCount大于核心大小

            if ((wc > maximumPoolSize || (timed && timedOut))     // worker数量大于maximumPoolSize
                && (wc > 1 || workQueue.isEmpty())) {            // workerCount大于1或者worker阻塞队列为空(在阻塞队列不为空时,需要保证至少有一个wc)
                if (compareAndDecrementWorkerCount(c))            // 比较并减少workerCount
                    // 返回null,不执行任务,该worker会退出
                    return null;
                // 跳过剩余部分,继续循环
                continue;
            }

            try {
                Runnable r = timed ?
                    workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :    // 等待指定时间
                    workQueue.take();                                        // 一直等待,直到有元素
                if (r != null)
                    return r;
                // 等待指定时间后,没有获取元素,则超时
                timedOut = true;
            } catch (InterruptedException retry) {
                // 抛出了被中断异常,重试,没有超时
                timedOut = false;
            }
        }
    }

processWorkerExit 기능은 다음과 같은 주요 요소 노동자에 리드가 종료 후크 기능을 종료 작업자에 호출

  1. 큐를 차단하면 이미 실행 할 일이 없다는 것을, 비어 있습니다.

  2. 셧다운 기능 호출 또는 shutdownNow의

이 기능은 유휴 스레드가 설정 한 노동자에서 제거 workerCount의 가치와 노동자를 줄이기 위해 중단 및 스레드 풀을 종료하려고하는지 여부에 따라 결정됩니다.

    private void processWorkerExit(Worker w, boolean completedAbruptly) {
        if (completedAbruptly) // 如果被中断,则需要减少workCount    // If abrupt, then workerCount wasn't adjusted
            decrementWorkerCount();
        // 获取可重入锁
        final ReentrantLock mainLock = this.mainLock;
        // 获取锁
        mainLock.lock();
        try {
            // 将worker完成的任务添加到总的完成任务中
            completedTaskCount += w.completedTasks;
            // 从workers集合中移除该worker
            workers.remove(w);
        } finally {
            // 释放锁
            mainLock.unlock();
        }
        // 尝试终止
        tryTerminate();
        // 获取线程池控制状态
        int c = ctl.get();
        if (runStateLessThan(c, STOP)) { // 小于STOP的运行状态
            if (!completedAbruptly) {
                int min = allowCoreThreadTimeOut ? 0 : corePoolSize;
                if (min == 0 && ! workQueue.isEmpty()) // 允许核心超时并且workQueue阻塞队列不为空
                    min = 1;
                if (workerCountOf(c) >= min) // workerCount大于等于min
                    // 直接返回
                    return; // replacement not needed
            }
            // 添加worker
            addWorker(null, false);
        }
    }

스레드 풀을 닫습니다

    public void shutdown() {
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            // 检查shutdown权限
            checkShutdownAccess();
            // 设置线程池控制状态为SHUTDOWN
            advanceRunState(SHUTDOWN);
            // 中断空闲worker
            interruptIdleWorkers();
            // 调用shutdown钩子函数
            onShutdown(); // hook for ScheduledThreadPoolExecutor
        } finally {
            mainLock.unlock();
        }
        // 尝试终止
        tryTerminate();
    }
    final void tryTerminate() {
        for (;;) { // 无限循环,确保操作成功
            // 获取线程池控制状态
            int c = ctl.get();
            if (isRunning(c) ||                                            // 线程池的运行状态为RUNNING
                runStateAtLeast(c, TIDYING) ||                            // 线程池的运行状态最小要大于TIDYING
                (runStateOf(c) == SHUTDOWN && ! workQueue.isEmpty()))    // 线程池的运行状态为SHUTDOWN并且workQueue队列不为null
                // 不能终止,直接返回
                return;
            if (workerCountOf(c) != 0) { // 线程池正在运行的worker数量不为0    // Eligible to terminate
                // 仅仅中断一个空闲的worker
                interruptIdleWorkers(ONLY_ONE);
                return;
            }
            // 获取线程池的锁
            final ReentrantLock mainLock = this.mainLock;
            // 获取锁
            mainLock.lock();
            try {
                if (ctl.compareAndSet(c, ctlOf(TIDYING, 0))) { // 比较并设置线程池控制状态为TIDYING
                    try {
                        // 终止,钩子函数
                        terminated();
                    } finally {
                        // 设置线程池控制状态为TERMINATED
                        ctl.set(ctlOf(TERMINATED, 0));
                        // 释放在termination条件上等待的所有线程
                        termination.signalAll();
                    }
                    return;
                }
            } finally {
                // 释放锁
                mainLock.unlock();
            }
            // else retry on failed CAS
        }
    }
    private void interruptIdleWorkers(boolean onlyOne) {
        // 线程池的锁
        final ReentrantLock mainLock = this.mainLock;
        // 获取锁
        mainLock.lock();
        try {
            for (Worker w : workers) { // 遍历workers队列
                // worker对应的线程
                Thread t = w.thread;
                if (!t.isInterrupted() && w.tryLock()) { // 线程未被中断并且成功获得锁
                    try {
                        // 中断线程
                        t.interrupt();
                    } catch (SecurityException ignore) {
                    } finally {
                        // 释放锁
                        w.unlock();
                    }
                }
                if (onlyOne) // 若只中断一个,则跳出循环
                    break;
            }
        } finally {
            // 释放锁
            mainLock.unlock();
        }
    }

추천

출처www.cnblogs.com/sxdtzhaoxinguo/p/12552259.html