El grupo de subprocesos de análisis de Java

subprocesos

Descripción general de subprocesos

  • ¿Cuál es el grupo de subprocesos

  • ¿Por qué utilizar un grupo de subprocesos

  • ventaja grupo de subprocesos

    • Primero: reducir el consumo de recursos. Al reutilizar el hilo ha sido creado para reducir la creación del hilo y la destrucción causada por el consumo.

    • En segundo lugar: la mejora de la velocidad de respuesta. Cuando llega la misión, la tarea no puede tener que esperar hasta la creación del hilo se puede implementar de inmediato.

    • Tercero: para mejorar la capacidad de gestión de hilos. Un hilo es un recurso escaso, si la creación ilimitada, no sólo consume recursos del sistema, sino también a reducir la estabilidad del sistema, utilizando un grupo de subprocesos se pueden unificar distribución, puesta a punto y el seguimiento. Pero para ser un uso razonable del grupo de subprocesos debe ser muy consciente de su principio.

Crear un hilo grupo de subprocesos y enviar la tarea

grupo de subprocesos de análisis Fuente

parámetros saben

  1. corePoolSize: El tamaño básico del grupo de subprocesos, al enviar un trabajo a la agrupación de hebras, grupo de subprocesos creará un hilo para realizar la tarea, incluso si el otro hilo de base libre puede realizar nuevas tareas será la creación de un hilo, hasta que es necesario realizar es mayor que el hilo del número de tareas creado cuando la piscina ya no es un tamaño básico. Si se llama a un grupo de subprocesos prestartAllCoreThreads método, grupo de subprocesos se crea de antemano y empezar todos los temas básicos.

  2. runnableTaskQueue: Columna tarea que almacena la tarea de bloquear la cola de espera para ser ejecutado. Puede seleccionar la siguiente cola de bloqueo.

  • ArrayBlockingQueue: una configuración basada en matrices acotado bloqueo de cola Esta cola FIFO (First In First Out) elementos ordenar principio.

  • LinkedBlockingQueue: el bloqueo de cola sobre la base de una estructura de lista, de acuerdo con esta cola FIFO (First In First Out) elemento a tratar, por lo general superior a un cierto ArrayBlockingQueue. método de fábrica estática Executors.newFixedThreadPool () utiliza esta cola.

  • SynchronousQueue: un elemento de cola de bloqueo no se almacena. Cada operación de inserción debe esperar hasta que otro subproceso llama a la operación de eliminación, o operación de inserción ha estado en un estado bloqueado, el rendimiento suele ser mayor que LinkedBlockingQueue, método de fábrica estática Executors.newCachedThreadPool utilizar esta cola.

  • PriorityBlockingQueue: una prioridad de colas infinitamente bloqueo.

  1. maximumPoolSize: el tamaño máximo del grupo de subprocesos, grupo de subprocesos permite crear el número máximo de subprocesos. Si la cola está llena, y el número de hilos que se han creado menos que el número máximo de subprocesos, el grupo de subprocesos volverá a crear un nuevo hilo para realizar la tarea. Vale la pena señalar que si se utiliza la tarea sin límites cola de este parámetro para ningún efecto.

  2. ThreadFactory: utiliza para establecer la fábrica para crear hilos, y la ayuda se puede ajustar muy significativo para cada uno creado por una fábrica de hilos de rosca el nombre, depuración y problemas de posicionamiento.

  3. RejectedExecutionHandler (política de saturación): Cuando las colas y los grupos de subprocesos están llenos, lo que indica que el grupo de subprocesos está saturado, se debe adoptar una estrategia para hacer frente a la nueva presentación de tareas. Por defecto, esta estrategia es AbortPolicy, se dijo que no podía lanzar una excepción cuando se trata de nuevas tareas.

  • CallerRunsPolicy: donde sólo el hilo de llamada para ejecutar la tarea.

  • DiscardOldestPolicy: tarea reciente cola de desecho y ejecutar la tarea actual.

  • DiscardPolicy: sin tratamiento, descartado.

  • Por supuesto, usted puede ser requerido para implementar una interfaz de RejectedExecutionHandler directiva personalizada en función del escenario de aplicación. Tales como la tala o la persistencia de tareas no pueden manejar.

  1. KeepAliveTime: actividad de los hilos tiempo de mantenimiento, después de que el grupo de subprocesos de trabajo inactivo, para mantener vivo el tiempo. Así que si una gran cantidad de tareas, y cada vez ejecución de la tarea es relativamente corto, se puede convertir esta vez, mejorar la utilización de la rosca.

  2. TimeUnit: unidades de tiempo de retención de actividad hilo, opcionalmente unidades de un día (días), h (horas), min (minutos), ms (milisegundos), microsegundo (microsegundos, milésima ms) y NS ( nanosegundos, milésima microsegundos).

  3. Otras propiedades de la clase


    // 线程池的控制状态:用来表示线程池的运行状态(整型的高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();

constructor

    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;
    }

Enviar trabajos

/*
* 进行下面三步
*
* 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. El aumento de workerCount atómica.

  2. Al usuario se le dio la tarea de envasado de un trabajador, trabajador y añadir a los trabajadores de recolección.

  3. Inicio subproceso de trabajo correspondiente, y el hilo comienza a ejecutar el método run del trabajador.

  4. Crear un trabajador de la acción de deshacer, el trabajador pronto será eliminado del conjunto de los trabajadores y reducir atómica 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;
}

misión

función runWorker realidad llevará a cabo una tarea determinada (es decir, el usuario llama al método run regrabable), y después de la realización de una determinada tarea, la tarea continuará tomando bloqueen la cola hasta que la cola es la obstrucción vacío (es decir, las tareas completadas). Durante la realización de una tarea determinada, se llama a la función de enlace, utilizando la función de enlace puede hacer algo de lógica definida por el usuario. En runWorker llamará a la función y función de enlace 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);
    }
}

Esta función se utiliza para obtener workerQueue objeto ejecutable desde el bloqueo de la cola, ya que la cola está bloqueada, espera por un tiempo limitado (sondeo) y espera infinita (take). En esta función y también responde a operación de apagado, la función shutdownNow, al detectar la agrupación de hebras está en el SHUTDOWN estado STOP o se devuelve null, y el objeto no devuelve Runnalbe bloqueado cola.

    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;
            }
        }
    }

función processWorkerExit se invoca en el trabajador para salir de la función de enlace, lo que conduce a la siguiente trabajador principal factores dejar de fumar

  1. El bloqueo de cola ya está vacío, que no hay tarea a ejecutar.

  2. La parada llamada de función o shutDownNow

Esta función se determinará en función de si o no el hilo vacío se interrumpe para reducir el valor de workerCount, y sacar al trabajador de los trabajadores establecidos y tratará de terminar el grupo de subprocesos.

    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);
        }
    }

Cerrar el grupo de subprocesos

    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();
        }
    }

Supongo que te gusta

Origin www.cnblogs.com/sxdtzhaoxinguo/p/12552259.html
Recomendado
Clasificación