aprendizaje del código fuente del grupo de subprocesos jdk-Executor

¿Qué son los hilos?

Una aplicación es un proceso (también hay varios). Un proceso tiene al menos un subproceso. El subproceso es privado para el proceso. Cuando finaliza el proceso, el subproceso terminará con él. Como se muestra abajo

97dde6ff717e5faab723e9da73b0931c.png

Por supuesto, hay algunos relacionados con la memoria, así que no profundizaré mucho aquí, solo entiendo los conceptos básicos, y los estudiantes que no entiendan pueden buscar por sí mismos.

¿Qué estados de vida tienen los hilos y cómo cambian?

Nuevo nuevo

EJECUTABLE, corre

BLOQUEADO, bloqueado

Esperando esperando

TIMED_WAITING, tiempo de espera agotado

TERMINADO

a77538e0e2c1ac0c26f5152bb176ac3a.png

Nota: los paquetes nativos de Java no son compatibles con las corrutinas y deben ser compatibles con el quasar que puede introducir a terceros.

¿Qué son los grupos de subprocesos de Java?

La función principal del grupo de subprocesos es un contenedor que se utiliza para administrar los subprocesos. A través de esto, se puede reducir la creación y liberación ilimitadas de subprocesos, lo que resulta en un control deficiente de los recursos del sistema. El grupo de subprocesos se puede asignar, ajustar y monitorear.

FixedThreadPool: un grupo de subprocesos con un tamaño fijo, el número de subprocesos se especifica cuando se crea y la cola de tareas es una cola ilimitada.

  1. CachedThreadPool: grupo de subprocesos en caché, la cantidad de subprocesos no es fija, se crearán nuevos subprocesos automáticamente según las necesidades, los subprocesos inactivos se mantendrán durante 60 segundos y la cola de tareas es SynchronousQueue.

  2. ScheduledThreadPool: un grupo de subprocesos de temporizador que admite la ejecución retrasada y la ejecución periódica de tareas.

  3. SingleThreadExecutor: grupo de subprocesos de un solo subproceso, solo un subproceso ejecuta tareas y la cola de tareas es una cola ilimitada.

  4. WorkStealingPool: grupo de subprocesos de robo de trabajo, cada subproceso tiene su propia cola de tareas y los subprocesos pueden robar la ejecución de tareas de las colas de tareas de otros subprocesos.

Uso básico del grupo de subprocesos

package com.executor;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @author: csh
 * @Date: 2023/3/6 23:02
 * @Description:固定大小的线程池,线程数一旦达到最大值,新任务就会在等待队列中等待。适用于预先知道任务数量的情况。
 */
public class FixedThreadPoolStudy {

    public static void main(String[] args) {
        // 创建一个包含5个线程的线程池
        ExecutorService executorService = Executors.newFixedThreadPool(5);
        // 提交10个任务
        for (int i = 1; i <= 10; i++) {
            executorService.execute(new Task(i));
        }
        // 关闭线程池
        executorService.shutdown();
    }
    static class Task implements Runnable {
        private int taskId;
        public Task(int taskId) {
            this.taskId = taskId;
        }
        @Override
        public void run() {
            System.out.println("任务" + taskId + "开始执行,当前线程名为" + Thread.currentThread().getName());
            try {
                // 模拟任务执行的耗时
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("任务" + taskId + "执行完毕,当前线程名为" + Thread.currentThread().getName());
        }
    }
}

resultado de la operación

任务1开始执行,当前线程名为pool-1-thread-1
任务2开始执行,当前线程名为pool-1-thread-2
任务3开始执行,当前线程名为pool-1-thread-3
任务4开始执行,当前线程名为pool-1-thread-4
任务5开始执行,当前线程名为pool-1-thread-5
任务3执行完毕,当前线程名为pool-1-thread-3
任务1执行完毕,当前线程名为pool-1-thread-1
任务7开始执行,当前线程名为pool-1-thread-1
任务2执行完毕,当前线程名为pool-1-thread-2
任务8开始执行,当前线程名为pool-1-thread-2
任务4执行完毕,当前线程名为pool-1-thread-4
任务9开始执行,当前线程名为pool-1-thread-4
任务5执行完毕,当前线程名为pool-1-thread-5
任务10开始执行,当前线程名为pool-1-thread-5
任务6开始执行,当前线程名为pool-1-thread-3
任务9执行完毕,当前线程名为pool-1-thread-4
任务10执行完毕,当前线程名为pool-1-thread-5
任务8执行完毕,当前线程名为pool-1-thread-2
任务7执行完毕,当前线程名为pool-1-thread-1
任务6执行完毕,当前线程名为pool-1-thread-3
package com.executor;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @author: csh
 * @Date: 2023/3/6 23:02
 * @Description:固定大小的线程池,线程数一旦达到最大值,新任务就会在等待队列中等待。适用于预先知道任务数量的情况。
 */
public class FixedThreadPoolStudy {

    public static void main(String[] args) {
        // 创建一个包含5个线程的线程池
        ExecutorService executorService = Executors.newFixedThreadPool(5);
        // 提交10个任务
        for (int i = 1; i <= 10; i++) {
            executorService.execute(new Task(i));
        }
        // 关闭线程池
        executorService.shutdown();
    }
    static class Task implements Runnable {
        private int taskId;
        public Task(int taskId) {
            this.taskId = taskId;
        }
        @Override
        public void run() {
            System.out.println("任务" + taskId + "开始执行,当前线程名为" + Thread.currentThread().getName());
            try {
                // 模拟任务执行的耗时
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("任务" + taskId + "执行完毕,当前线程名为" + Thread.currentThread().getName());
        }
    }
}

resultado

任务1开始执行,当前线程名为pool-1-thread-1
任务2开始执行,当前线程名为pool-1-thread-2
任务3开始执行,当前线程名为pool-1-thread-3
任务4开始执行,当前线程名为pool-1-thread-4
任务5开始执行,当前线程名为pool-1-thread-5
任务3执行完毕,当前线程名为pool-1-thread-3
任务1执行完毕,当前线程名为pool-1-thread-1
任务7开始执行,当前线程名为pool-1-thread-1
任务6开始执行,当前线程名为pool-1-thread-3
任务2执行完毕,当前线程名为pool-1-thread-2
任务8开始执行,当前线程名为pool-1-thread-2
任务4执行完毕,当前线程名为pool-1-thread-4
任务5执行完毕,当前线程名为pool-1-thread-5
任务9开始执行,当前线程名为pool-1-thread-4
任务10开始执行,当前线程名为pool-1-thread-5
任务6执行完毕,当前线程名为pool-1-thread-3
任务8执行完毕,当前线程名为pool-1-thread-2
任务9执行完毕,当前线程名为pool-1-thread-4
任务7执行完毕,当前线程名为pool-1-thread-1
任务10执行完毕,当前线程名为pool-1-thread-5
package com.executor;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
 *
 * 功能描述: SingleThreadExecutor是一个只有一个线程的线程池,用于顺序执行任务。
 *
 * @param:
 * @return: 
 * @auther: csh
 * @date: 2023/3/6 11:09 下午
 */
public class SingleThreadExecutorStudy {
    public static void main(String[] args) {
        // 创建一个只有一个线程的线程池
        ExecutorService executorService = Executors.newSingleThreadExecutor();
        // 提交10个任务
        for (int i = 1; i <= 10; i++) {
            executorService.execute(new Task(i));
        }
        // 关闭线程池
        executorService.shutdown();
    }
    static class Task implements Runnable {
        private int taskId;
        public Task(int taskId) {
            this.taskId = taskId;
        }
        @Override
        public void run() {
            System.out.println("任务" + taskId + "开始执行,当前线程名为" + Thread.currentThread().getName());
            try {
                // 模拟任务执行的耗时
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("任务" + taskId + "执行完毕,当前线程名为" + Thread.currentThread().getName());
        }
    }
}

El resultado (se puede ver que solo se está ejecutando un hilo debajo)

任务1开始执行,当前线程名为pool-1-thread-1
任务1执行完毕,当前线程名为pool-1-thread-1
任务2开始执行,当前线程名为pool-1-thread-1
任务2执行完毕,当前线程名为pool-1-thread-1
任务3开始执行,当前线程名为pool-1-thread-1
任务3执行完毕,当前线程名为pool-1-thread-1
任务4开始执行,当前线程名为pool-1-thread-1
任务4执行完毕,当前线程名为pool-1-thread-1
任务5开始执行,当前线程名为pool-1-thread-1
任务5执行完毕,当前线程名为pool-1-thread-1
任务6开始执行,当前线程名为pool-1-thread-1
任务6执行完毕,当前线程名为pool-1-thread-1
任务7开始执行,当前线程名为pool-1-thread-1
任务7执行完毕,当前线程名为pool-1-thread-1
任务8开始执行,当前线程名为pool-1-thread-1
任务8执行完毕,当前线程名为pool-1-thread-1
任务9开始执行,当前线程名为pool-1-thread-1
任务9执行完毕,当前线程名为pool-1-thread-1
任务10开始执行,当前线程名为pool-1-thread-1
任务10执行完毕,当前线程名为pool-1-thread-1
package com.executor;

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
/**
 *
 * 功能描述: ScheduledThreadPool是一个可以执行定时任务的线程池,可以实现延迟执行和周期执行。
 *
 * @param: 
 * @return: 
 * @auther: csh
 * @date: 2023/3/6 11:13 下午
 */
public class ScheduledThreadPoolStudy {
    public static void main(String[] args) {
        // 创建一个可以执行定时任务的线程池
        ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(5);
        // 提交10个定时任务,每个任务延迟1秒后执行,每个任务执行周期为2秒
        for (int i = 1; i <= 10; i++) {
            scheduledExecutorService.scheduleAtFixedRate(new Task(i), 1, 2, TimeUnit.SECONDS);
        }
        // 关闭线程池
       // scheduledExecutorService.shutdown();
    }
    static class Task implements Runnable {
        private int taskId;
        public Task(int taskId) {
            this.taskId = taskId;
        }
        @Override
        public void run() {
            System.out.println("任务" + taskId + "开始执行,当前线程名为" + Thread.currentThread().getName());
            try {
                // 模拟任务执行的耗时
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("任务" + taskId + "执行完毕,当前线程名为" + Thread.currentThread().getName());
        }
    }
}

Como resultado, puede ver que se implementa la ejecución periódica

任务4开始执行,当前线程名为pool-1-thread-2
任务10执行完毕,当前线程名为pool-1-thread-3
任务5开始执行,当前线程名为pool-1-thread-3
任务1执行完毕,当前线程名为pool-1-thread-1
任务6开始执行,当前线程名为pool-1-thread-1
任务2执行完毕,当前线程名为pool-1-thread-4
任务7开始执行,当前线程名为pool-1-thread-4
任务3执行完毕,当前线程名为pool-1-thread-5
任务8开始执行,当前线程名为pool-1-thread-5
任务4执行完毕,当前线程名为pool-1-thread-2
任务9开始执行,当前线程名为pool-1-thread-2
任务5执行完毕,当前线程名为pool-1-thread-3
任务10开始执行,当前线程名为pool-1-thread-3
任务6执行完毕,当前线程名为pool-1-thread-1
任务1开始执行,当前线程名为pool-1-thread-1
任务7执行完毕,当前线程名为pool-1-thread-4
任务2开始执行,当前线程名为pool-1-thread-4
任务8执行完毕,当前线程名为pool-1-thread-5
任务3开始执行,当前线程名为pool-1-thread-5
任务9执行完毕,当前线程名为pool-1-thread-2
任务4开始执行,当前线程名为pool-1-thread-2
任务10执行完毕,当前线程名为pool-1-thread-3
任务5开始执行,当前线程名为pool-1-thread-3
任务1执行完毕,当前线程名为pool-1-thread-1
任务6开始执行,当前线程名为pool-1-thread-1
任务2执行完毕,当前线程名为pool-1-thread-4
任务7开始执行,当前线程名为pool-1-thread-4
任务3执行完毕,当前线程名为pool-1-thread-5
任务8开始执行,当前线程名为pool-1-thread-5
任务4执行完毕,当前线程名为pool-1-thread-2
任务9开始执行,当前线程名为pool-1-thread-2
任务5执行完毕,当前线程名为pool-1-thread-3
任务10开始执行,当前线程名为pool-1-thread-3
任务6执行完毕,当前线程名为pool-1-thread-1
任务1开始执行,当前线程名为pool-1-thread-1
任务8执行完毕,当前线程名为pool-1-thread-5
任务2开始执行,当前线程名为pool-1-thread-5
任务7执行完毕,当前线程名为pool-1-thread-4
任务3开始执行,当前线程名为pool-1-thread-4
任务9执行完毕,当前线程名为pool-1-thread-2
任务10执行完毕,当前线程名为pool-1-thread-3
任务4开始执行,当前线程名为pool-1-thread-2
任务5开始执行,当前线程名为pool-1-thread-3
任务1执行完毕,当前线程名为pool-1-thread-1
任务6开始执行,当前线程名为pool-1-thread-1
任务2执行完毕,当前线程名为pool-1-thread-5
任务7开始执行,当前线程名为pool-1-thread-5
任务3执行完毕,当前线程名为pool-1-thread-4
任务8开始执行,当前线程名为pool-1-thread-4
任务4执行完毕,当前线程名为pool-1-thread-2
任务5执行完毕,当前线程名为pool-1-thread-3
任务9开始执行,当前线程名为pool-1-thread-3
任务10开始执行,当前线程名为pool-1-thread-2
任务6执行完毕,当前线程名为pool-1-thread-1
任务1开始执行,当前线程名为pool-1-thread-1
任务8执行完毕,当前线程名为pool-1-thread-4
任务2开始执行,当前线程名为pool-1-thread-4
任务7执行完毕,当前线程名为pool-1-thread-5
任务3开始执行,当前线程名为pool-1-thread-5
任务9执行完毕,当前线程名为pool-1-thread-3
任务10执行完毕,当前线程名为pool-1-thread-2
任务4开始执行,当前线程名为pool-1-thread-3
任务5开始执行,当前线程名为pool-1-thread-2
任务1执行完毕,当前线程名为pool-1-thread-1
任务6开始执行,当前线程名为pool-1-thread-1
任务3执行完毕,当前线程名为pool-1-thread-5
任务7开始执行,当前线程名为pool-1-thread-5
任务2执行完毕,当前线程名为pool-1-thread-4
任务8开始执行,当前线程名为pool-1-thread-4
任务4执行完毕,当前线程名为pool-1-thread-3
任务5执行完毕,当前线程名为pool-1-thread-2
任务9开始执行,当前线程名为pool-1-thread-3
任务10开始执行,当前线程名为pool-1-thread-2
任务6执行完毕,当前线程名为pool-1-thread-1
任务1开始执行,当前线程名为pool-1-thread-1
任务7执行完毕,当前线程名为pool-1-thread-5
任务2开始执行,当前线程名为pool-1-thread-5
任务8执行完毕,当前线程名为pool-1-thread-4
任务3开始执行,当前线程名为pool-1-thread-4
任务9执行完毕,当前线程名为pool-1-thread-3
任务4开始执行,当前线程名为pool-1-thread-3
任务10执行完毕,当前线程名为pool-1-thread-2
任务5开始执行,当前线程名为pool-1-thread-2
任务1执行完毕,当前线程名为pool-1-thread-1
任务6开始执行,当前线程名为pool-1-thread-1
任务2执行完毕,当前线程名为pool-1-thread-5
任务7开始执行,当前线程名为pool-1-thread-5
任务3执行完毕,当前线程名为pool-1-thread-4
任务8开始执行,当前线程名为pool-1-thread-4
任务4执行完毕,当前线程名为pool-1-thread-3
任务9开始执行,当前线程名为pool-1-thread-3
任务5执行完毕,当前线程名为pool-1-thread-2
任务10开始执行,当前线程名为pool-1-thread-2
任务6执行完毕,当前线程名为pool-1-thread-1
任务1开始执行,当前线程名为pool-1-thread-1
任务8执行完毕,当前线程名为pool-1-thread-4
任务7执行完毕,当前线程名为pool-1-thread-5
任务2开始执行,当前线程名为pool-1-thread-4
任务3开始执行,当前线程名为pool-1-thread-5
任务9执行完毕,当前线程名为pool-1-thread-3
任务4开始执行,当前线程名为pool-1-thread-3
任务10执行完毕,当前线程名为pool-1-thread-2
任务5开始执行,当前线程名为pool-1-thread-2
任务1执行完毕,当前线程名为pool-1-thread-1
任务6开始执行,当前线程名为pool-1-thread-1
任务3执行完毕,当前线程名为pool-1-thread-5
任务2执行完毕,当前线程名为pool-1-thread-4
任务7开始执行,当前线程名为pool-1-thread-5
任务8开始执行,当前线程名为pool-1-thread-4
任务4执行完毕,当前线程名为pool-1-thread-3
任务9开始执行,当前线程名为pool-1-thread-3
任务5执行完毕,当前线程名为pool-1-thread-2
任务10开始执行,当前线程名为pool-1-thread-2
package com.executor;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
/**
 *
 * 功能描述: WorkStealingPool是一个基于工作窃取算法的线程池,用于提高多核CPU的利用率。
 *
 * @param:
 * @return: 
 * @auther: csh
 * @date: 2023/3/6 11:18 下午
 */
public class WorkStealingPoolStudy {
    public static void main(String[] args) {
        // 获取当前系统的CPU核心数
        int processors = Runtime.getRuntime().availableProcessors();
        // 创建一个基于工作窃取算法的线程池
        ExecutorService executorService = Executors.newWorkStealingPool(processors);
        // 提交10个任务
        for (int i = 1; i <= 1000; i++) {
            executorService.execute(new Task(i));
        }
        // 等待所有任务执行完毕
        try {
            executorService.awaitTermination(1, TimeUnit.MINUTES);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // 关闭线程池
        executorService.shutdown();
    }
    static class Task implements Runnable {
        private int taskId;
        public Task(int taskId) {
            this.taskId = taskId;
        }
        @Override
        public void run() {
            System.out.println("任务" + taskId + "开始执行,当前线程名为" + Thread.currentThread().getName());
            try {
                // 模拟任务执行的耗时
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("任务" + taskId + "执行完毕,当前线程名为" + Thread.currentThread().getName());
        }
    }
}

resultado

任务8开始执行,当前线程名为ForkJoinPool-1-worker-0
任务4开始执行,当前线程名为ForkJoinPool-1-worker-4
任务5开始执行,当前线程名为ForkJoinPool-1-worker-5
任务2开始执行,当前线程名为ForkJoinPool-1-worker-2
任务3开始执行,当前线程名为ForkJoinPool-1-worker-3
任务6开始执行,当前线程名为ForkJoinPool-1-worker-6
任务1开始执行,当前线程名为ForkJoinPool-1-worker-1
任务7开始执行,当前线程名为ForkJoinPool-1-worker-7
任务8执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务1执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务2执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务5执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务12开始执行,当前线程名为ForkJoinPool-1-worker-5
任务4执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务13开始执行,当前线程名为ForkJoinPool-1-worker-4
任务7执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务14开始执行,当前线程名为ForkJoinPool-1-worker-7
任务11开始执行,当前线程名为ForkJoinPool-1-worker-2
任务3执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务6执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务9开始执行,当前线程名为ForkJoinPool-1-worker-0
任务10开始执行,当前线程名为ForkJoinPool-1-worker-1
任务16开始执行,当前线程名为ForkJoinPool-1-worker-6
任务15开始执行,当前线程名为ForkJoinPool-1-worker-3
任务12执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务10执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务18开始执行,当前线程名为ForkJoinPool-1-worker-1
任务15执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务19开始执行,当前线程名为ForkJoinPool-1-worker-3
任务13执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务20开始执行,当前线程名为ForkJoinPool-1-worker-4
任务9执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务21开始执行,当前线程名为ForkJoinPool-1-worker-0
任务11执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务22开始执行,当前线程名为ForkJoinPool-1-worker-2
任务14执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务23开始执行,当前线程名为ForkJoinPool-1-worker-7
任务16执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务24开始执行,当前线程名为ForkJoinPool-1-worker-6
任务17开始执行,当前线程名为ForkJoinPool-1-worker-5
任务19执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务23执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务24执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务25开始执行,当前线程名为ForkJoinPool-1-worker-3
任务26开始执行,当前线程名为ForkJoinPool-1-worker-7
任务17执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务20执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务27开始执行,当前线程名为ForkJoinPool-1-worker-6
任务22执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务29开始执行,当前线程名为ForkJoinPool-1-worker-4
任务30开始执行,当前线程名为ForkJoinPool-1-worker-2
任务28开始执行,当前线程名为ForkJoinPool-1-worker-5
任务18执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务21执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务31开始执行,当前线程名为ForkJoinPool-1-worker-1
任务32开始执行,当前线程名为ForkJoinPool-1-worker-0
任务26执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务29执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务30执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务33开始执行,当前线程名为ForkJoinPool-1-worker-7
任务31执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务27执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务25执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务28执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务38开始执行,当前线程名为ForkJoinPool-1-worker-3
任务37开始执行,当前线程名为ForkJoinPool-1-worker-6
任务36开始执行,当前线程名为ForkJoinPool-1-worker-1
任务35开始执行,当前线程名为ForkJoinPool-1-worker-4
任务34开始执行,当前线程名为ForkJoinPool-1-worker-2
任务39开始执行,当前线程名为ForkJoinPool-1-worker-5
任务32执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务40开始执行,当前线程名为ForkJoinPool-1-worker-0
任务34执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务41开始执行,当前线程名为ForkJoinPool-1-worker-2
任务39执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务42开始执行,当前线程名为ForkJoinPool-1-worker-5
任务35执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务43开始执行,当前线程名为ForkJoinPool-1-worker-4
任务36执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务44开始执行,当前线程名为ForkJoinPool-1-worker-1
任务33执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务38执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务45开始执行,当前线程名为ForkJoinPool-1-worker-3
任务46开始执行,当前线程名为ForkJoinPool-1-worker-7
任务37执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务47开始执行,当前线程名为ForkJoinPool-1-worker-6
任务40执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务48开始执行,当前线程名为ForkJoinPool-1-worker-0
任务44执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务49开始执行,当前线程名为ForkJoinPool-1-worker-1
任务42执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务43执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务45执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务41执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务52开始执行,当前线程名为ForkJoinPool-1-worker-3
任务51开始执行,当前线程名为ForkJoinPool-1-worker-4
任务50开始执行,当前线程名为ForkJoinPool-1-worker-5
任务53开始执行,当前线程名为ForkJoinPool-1-worker-2
任务47执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务54开始执行,当前线程名为ForkJoinPool-1-worker-6
任务46执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务48执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务55开始执行,当前线程名为ForkJoinPool-1-worker-7
任务56开始执行,当前线程名为ForkJoinPool-1-worker-0
任务49执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务57开始执行,当前线程名为ForkJoinPool-1-worker-1
任务51执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务58开始执行,当前线程名为ForkJoinPool-1-worker-4
任务52执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务59开始执行,当前线程名为ForkJoinPool-1-worker-3
任务53执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务60开始执行,当前线程名为ForkJoinPool-1-worker-2
任务56执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务54执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务61开始执行,当前线程名为ForkJoinPool-1-worker-0
任务55执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务63开始执行,当前线程名为ForkJoinPool-1-worker-7
任务50执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务64开始执行,当前线程名为ForkJoinPool-1-worker-5
任务62开始执行,当前线程名为ForkJoinPool-1-worker-6
任务57执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务62执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务64执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务60执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务63执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务59执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务61执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务67开始执行,当前线程名为ForkJoinPool-1-worker-2
任务58执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务68开始执行,当前线程名为ForkJoinPool-1-worker-6
任务71开始执行,当前线程名为ForkJoinPool-1-worker-0
任务72开始执行,当前线程名为ForkJoinPool-1-worker-4
任务69开始执行,当前线程名为ForkJoinPool-1-worker-7
任务70开始执行,当前线程名为ForkJoinPool-1-worker-3
任务66开始执行,当前线程名为ForkJoinPool-1-worker-5
任务65开始执行,当前线程名为ForkJoinPool-1-worker-1
任务67执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务66执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务65执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务70执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务72执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务68执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务71执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务69执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务79开始执行,当前线程名为ForkJoinPool-1-worker-0
任务78开始执行,当前线程名为ForkJoinPool-1-worker-6
任务77开始执行,当前线程名为ForkJoinPool-1-worker-4
任务76开始执行,当前线程名为ForkJoinPool-1-worker-3
任务75开始执行,当前线程名为ForkJoinPool-1-worker-1
任务74开始执行,当前线程名为ForkJoinPool-1-worker-5
任务73开始执行,当前线程名为ForkJoinPool-1-worker-2
任务80开始执行,当前线程名为ForkJoinPool-1-worker-7
任务75执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务79执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务73执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务76执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务84开始执行,当前线程名为ForkJoinPool-1-worker-3
任务78执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务82开始执行,当前线程名为ForkJoinPool-1-worker-0
任务81开始执行,当前线程名为ForkJoinPool-1-worker-1
任务85开始执行,当前线程名为ForkJoinPool-1-worker-6
任务83开始执行,当前线程名为ForkJoinPool-1-worker-2
任务80执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务86开始执行,当前线程名为ForkJoinPool-1-worker-7
任务74执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务77执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务87开始执行,当前线程名为ForkJoinPool-1-worker-5
任务88开始执行,当前线程名为ForkJoinPool-1-worker-4
任务82执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务84执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务89开始执行,当前线程名为ForkJoinPool-1-worker-3
任务81执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务85执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务86执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务90开始执行,当前线程名为ForkJoinPool-1-worker-1
任务83执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务92开始执行,当前线程名为ForkJoinPool-1-worker-2
任务91开始执行,当前线程名为ForkJoinPool-1-worker-0
任务93开始执行,当前线程名为ForkJoinPool-1-worker-6
任务94开始执行,当前线程名为ForkJoinPool-1-worker-7
任务88执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务95开始执行,当前线程名为ForkJoinPool-1-worker-4
任务87执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务96开始执行,当前线程名为ForkJoinPool-1-worker-5
任务92执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务94执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务98开始执行,当前线程名为ForkJoinPool-1-worker-7
任务95执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务99开始执行,当前线程名为ForkJoinPool-1-worker-4
任务97开始执行,当前线程名为ForkJoinPool-1-worker-2
任务89执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务100开始执行,当前线程名为ForkJoinPool-1-worker-3
任务91执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务101开始执行,当前线程名为ForkJoinPool-1-worker-0
任务93执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务102开始执行,当前线程名为ForkJoinPool-1-worker-6
任务90执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务103开始执行,当前线程名为ForkJoinPool-1-worker-1
任务96执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务104开始执行,当前线程名为ForkJoinPool-1-worker-5
任务97执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务104执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务101执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务100执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务105开始执行,当前线程名为ForkJoinPool-1-worker-2
任务99执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务107开始执行,当前线程名为ForkJoinPool-1-worker-4
任务108开始执行,当前线程名为ForkJoinPool-1-worker-5
任务98执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务109开始执行,当前线程名为ForkJoinPool-1-worker-7
任务102执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务111开始执行,当前线程名为ForkJoinPool-1-worker-6
任务103执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务110开始执行,当前线程名为ForkJoinPool-1-worker-0
任务106开始执行,当前线程名为ForkJoinPool-1-worker-3
任务112开始执行,当前线程名为ForkJoinPool-1-worker-1
任务110执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务112执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务113开始执行,当前线程名为ForkJoinPool-1-worker-0
任务107执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务114开始执行,当前线程名为ForkJoinPool-1-worker-1
任务115开始执行,当前线程名为ForkJoinPool-1-worker-4
任务105执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务111执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务109执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务108执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务106执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务119开始执行,当前线程名为ForkJoinPool-1-worker-5
任务118开始执行,当前线程名为ForkJoinPool-1-worker-7
任务117开始执行,当前线程名为ForkJoinPool-1-worker-6
任务116开始执行,当前线程名为ForkJoinPool-1-worker-2
任务120开始执行,当前线程名为ForkJoinPool-1-worker-3
任务114执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务121开始执行,当前线程名为ForkJoinPool-1-worker-1
任务113执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务115执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务122开始执行,当前线程名为ForkJoinPool-1-worker-4
任务123开始执行,当前线程名为ForkJoinPool-1-worker-0
任务116执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务118执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务124开始执行,当前线程名为ForkJoinPool-1-worker-2
任务125开始执行,当前线程名为ForkJoinPool-1-worker-7
任务119执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务120执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务117执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务126开始执行,当前线程名为ForkJoinPool-1-worker-5
任务128开始执行,当前线程名为ForkJoinPool-1-worker-6
任务127开始执行,当前线程名为ForkJoinPool-1-worker-3
任务125执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务129开始执行,当前线程名为ForkJoinPool-1-worker-7
任务123执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务130开始执行,当前线程名为ForkJoinPool-1-worker-0
任务121执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务124执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务122执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务133开始执行,当前线程名为ForkJoinPool-1-worker-4
任务132开始执行,当前线程名为ForkJoinPool-1-worker-2
任务131开始执行,当前线程名为ForkJoinPool-1-worker-1
任务128执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务127执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务126执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务135开始执行,当前线程名为ForkJoinPool-1-worker-3
任务134开始执行,当前线程名为ForkJoinPool-1-worker-6
任务136开始执行,当前线程名为ForkJoinPool-1-worker-5
任务129执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务132执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务130执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务131执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务133执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务137开始执行,当前线程名为ForkJoinPool-1-worker-7
任务138开始执行,当前线程名为ForkJoinPool-1-worker-2
任务141开始执行,当前线程名为ForkJoinPool-1-worker-4
任务139开始执行,当前线程名为ForkJoinPool-1-worker-0
任务140开始执行,当前线程名为ForkJoinPool-1-worker-1
任务134执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务135执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务136执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务143开始执行,当前线程名为ForkJoinPool-1-worker-3
任务144开始执行,当前线程名为ForkJoinPool-1-worker-5
任务142开始执行,当前线程名为ForkJoinPool-1-worker-6
任务137执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务141执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务145开始执行,当前线程名为ForkJoinPool-1-worker-7
任务138执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务146开始执行,当前线程名为ForkJoinPool-1-worker-4
任务139执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务147开始执行,当前线程名为ForkJoinPool-1-worker-2
任务148开始执行,当前线程名为ForkJoinPool-1-worker-0
任务140执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务149开始执行,当前线程名为ForkJoinPool-1-worker-1
任务143执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务142执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务150开始执行,当前线程名为ForkJoinPool-1-worker-3
任务151开始执行,当前线程名为ForkJoinPool-1-worker-6
任务144执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务152开始执行,当前线程名为ForkJoinPool-1-worker-5
任务145执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务153开始执行,当前线程名为ForkJoinPool-1-worker-7
任务148执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务149执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务154开始执行,当前线程名为ForkJoinPool-1-worker-0
任务155开始执行,当前线程名为ForkJoinPool-1-worker-1
任务146执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务147执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务157开始执行,当前线程名为ForkJoinPool-1-worker-2
任务156开始执行,当前线程名为ForkJoinPool-1-worker-4
任务151执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务158开始执行,当前线程名为ForkJoinPool-1-worker-6
任务152执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务159开始执行,当前线程名为ForkJoinPool-1-worker-5
任务150执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务160开始执行,当前线程名为ForkJoinPool-1-worker-3
任务157执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务161开始执行,当前线程名为ForkJoinPool-1-worker-2
任务158执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务162开始执行,当前线程名为ForkJoinPool-1-worker-6
任务155执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务153执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务163开始执行,当前线程名为ForkJoinPool-1-worker-1
任务164开始执行,当前线程名为ForkJoinPool-1-worker-7
任务156执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务165开始执行,当前线程名为ForkJoinPool-1-worker-4
任务154执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务166开始执行,当前线程名为ForkJoinPool-1-worker-0
任务159执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务167开始执行,当前线程名为ForkJoinPool-1-worker-5
任务160执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务168开始执行,当前线程名为ForkJoinPool-1-worker-3
任务161执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务169开始执行,当前线程名为ForkJoinPool-1-worker-2
任务164执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务163执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务170开始执行,当前线程名为ForkJoinPool-1-worker-7
任务171开始执行,当前线程名为ForkJoinPool-1-worker-1
任务165执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务166执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务162执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务173开始执行,当前线程名为ForkJoinPool-1-worker-0
任务172开始执行,当前线程名为ForkJoinPool-1-worker-4
任务174开始执行,当前线程名为ForkJoinPool-1-worker-6
任务167执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务175开始执行,当前线程名为ForkJoinPool-1-worker-5
任务168执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务176开始执行,当前线程名为ForkJoinPool-1-worker-3
任务171执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务174执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务177开始执行,当前线程名为ForkJoinPool-1-worker-1
任务178开始执行,当前线程名为ForkJoinPool-1-worker-6
任务169执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务173执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务179开始执行,当前线程名为ForkJoinPool-1-worker-2
任务180开始执行,当前线程名为ForkJoinPool-1-worker-0
任务170执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务181开始执行,当前线程名为ForkJoinPool-1-worker-7
任务172执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务182开始执行,当前线程名为ForkJoinPool-1-worker-4
任务175执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务183开始执行,当前线程名为ForkJoinPool-1-worker-5
任务176执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务184开始执行,当前线程名为ForkJoinPool-1-worker-3
任务181执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务185开始执行,当前线程名为ForkJoinPool-1-worker-7
任务177执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务180执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务186开始执行,当前线程名为ForkJoinPool-1-worker-1
任务187开始执行,当前线程名为ForkJoinPool-1-worker-0
任务178执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务179执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务189开始执行,当前线程名为ForkJoinPool-1-worker-2
任务188开始执行,当前线程名为ForkJoinPool-1-worker-6
任务182执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务190开始执行,当前线程名为ForkJoinPool-1-worker-4
任务183执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务184执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务191开始执行,当前线程名为ForkJoinPool-1-worker-5
任务192开始执行,当前线程名为ForkJoinPool-1-worker-3
任务185执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务193开始执行,当前线程名为ForkJoinPool-1-worker-7
任务186执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务187执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务188执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务194开始执行,当前线程名为ForkJoinPool-1-worker-1
任务189执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务197开始执行,当前线程名为ForkJoinPool-1-worker-2
任务195开始执行,当前线程名为ForkJoinPool-1-worker-0
任务190执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务198开始执行,当前线程名为ForkJoinPool-1-worker-4
任务196开始执行,当前线程名为ForkJoinPool-1-worker-6
任务192执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务199开始执行,当前线程名为ForkJoinPool-1-worker-3
任务191执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务200开始执行,当前线程名为ForkJoinPool-1-worker-5
任务194执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务197执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务202开始执行,当前线程名为ForkJoinPool-1-worker-2
任务201开始执行,当前线程名为ForkJoinPool-1-worker-1
任务193执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务203开始执行,当前线程名为ForkJoinPool-1-worker-7
任务198执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务195执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务205开始执行,当前线程名为ForkJoinPool-1-worker-0
任务204开始执行,当前线程名为ForkJoinPool-1-worker-4
任务196执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务206开始执行,当前线程名为ForkJoinPool-1-worker-6
任务199执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务207开始执行,当前线程名为ForkJoinPool-1-worker-3
任务200执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务208开始执行,当前线程名为ForkJoinPool-1-worker-5
任务203执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务209开始执行,当前线程名为ForkJoinPool-1-worker-7
任务202执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务210开始执行,当前线程名为ForkJoinPool-1-worker-2
任务201执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务211开始执行,当前线程名为ForkJoinPool-1-worker-1
任务205执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务212开始执行,当前线程名为ForkJoinPool-1-worker-0
任务206执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务213开始执行,当前线程名为ForkJoinPool-1-worker-6
任务204执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务214开始执行,当前线程名为ForkJoinPool-1-worker-4
任务207执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务215开始执行,当前线程名为ForkJoinPool-1-worker-3
任务208执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务216开始执行,当前线程名为ForkJoinPool-1-worker-5
任务209执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务217开始执行,当前线程名为ForkJoinPool-1-worker-7
任务213执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务212执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务219开始执行,当前线程名为ForkJoinPool-1-worker-0
任务211执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务210执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务221开始执行,当前线程名为ForkJoinPool-1-worker-2
任务220开始执行,当前线程名为ForkJoinPool-1-worker-1
任务218开始执行,当前线程名为ForkJoinPool-1-worker-6
任务214执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务222开始执行,当前线程名为ForkJoinPool-1-worker-4
任务215执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务223开始执行,当前线程名为ForkJoinPool-1-worker-3
任务216执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务224开始执行,当前线程名为ForkJoinPool-1-worker-5
任务217执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务225开始执行,当前线程名为ForkJoinPool-1-worker-7
任务221执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务218执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务226开始执行,当前线程名为ForkJoinPool-1-worker-2
任务219执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务227开始执行,当前线程名为ForkJoinPool-1-worker-6
任务228开始执行,当前线程名为ForkJoinPool-1-worker-0
任务220执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务229开始执行,当前线程名为ForkJoinPool-1-worker-1
任务222执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务224执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务230开始执行,当前线程名为ForkJoinPool-1-worker-4
任务231开始执行,当前线程名为ForkJoinPool-1-worker-5
任务223执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务232开始执行,当前线程名为ForkJoinPool-1-worker-3
任务225执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务233开始执行,当前线程名为ForkJoinPool-1-worker-7
任务226执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务227执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务234开始执行,当前线程名为ForkJoinPool-1-worker-2
任务228执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务236开始执行,当前线程名为ForkJoinPool-1-worker-0
任务235开始执行,当前线程名为ForkJoinPool-1-worker-6
任务229执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务237开始执行,当前线程名为ForkJoinPool-1-worker-1
任务230执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务238开始执行,当前线程名为ForkJoinPool-1-worker-4
任务231执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务239开始执行,当前线程名为ForkJoinPool-1-worker-5
任务232执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务240开始执行,当前线程名为ForkJoinPool-1-worker-3
任务236执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务237执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务233执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务242开始执行,当前线程名为ForkJoinPool-1-worker-1
任务243开始执行,当前线程名为ForkJoinPool-1-worker-7
任务241开始执行,当前线程名为ForkJoinPool-1-worker-0
任务234执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务235执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务244开始执行,当前线程名为ForkJoinPool-1-worker-2
任务245开始执行,当前线程名为ForkJoinPool-1-worker-6
任务240执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务238执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务246开始执行,当前线程名为ForkJoinPool-1-worker-4
任务239执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务247开始执行,当前线程名为ForkJoinPool-1-worker-3
任务248开始执行,当前线程名为ForkJoinPool-1-worker-5
任务243执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务249开始执行,当前线程名为ForkJoinPool-1-worker-7
任务244执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务242执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务250开始执行,当前线程名为ForkJoinPool-1-worker-2
任务251开始执行,当前线程名为ForkJoinPool-1-worker-1
任务245执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务241执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务252开始执行,当前线程名为ForkJoinPool-1-worker-6
任务253开始执行,当前线程名为ForkJoinPool-1-worker-0
任务246执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务248执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务254开始执行,当前线程名为ForkJoinPool-1-worker-4
任务255开始执行,当前线程名为ForkJoinPool-1-worker-5
任务247执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务256开始执行,当前线程名为ForkJoinPool-1-worker-3
任务249执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务250执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务252执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务254执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务251执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务253执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务261开始执行,当前线程名为ForkJoinPool-1-worker-6
任务262开始执行,当前线程名为ForkJoinPool-1-worker-1
任务257开始执行,当前线程名为ForkJoinPool-1-worker-7
任务259开始执行,当前线程名为ForkJoinPool-1-worker-0
任务260开始执行,当前线程名为ForkJoinPool-1-worker-4
任务258开始执行,当前线程名为ForkJoinPool-1-worker-2
任务255执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务263开始执行,当前线程名为ForkJoinPool-1-worker-5
任务256执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务264开始执行,当前线程名为ForkJoinPool-1-worker-3
任务262执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务260执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务261执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务258执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务257执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务259执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务263执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务264执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务265开始执行,当前线程名为ForkJoinPool-1-worker-3
任务266开始执行,当前线程名为ForkJoinPool-1-worker-6
任务267开始执行,当前线程名为ForkJoinPool-1-worker-5
任务268开始执行,当前线程名为ForkJoinPool-1-worker-1
任务269开始执行,当前线程名为ForkJoinPool-1-worker-4
任务270开始执行,当前线程名为ForkJoinPool-1-worker-2
任务271开始执行,当前线程名为ForkJoinPool-1-worker-0
任务272开始执行,当前线程名为ForkJoinPool-1-worker-7
任务267执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务270执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务272执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务271执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务266执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务269执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务265执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务273开始执行,当前线程名为ForkJoinPool-1-worker-5
任务268执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务274开始执行,当前线程名为ForkJoinPool-1-worker-1
任务275开始执行,当前线程名为ForkJoinPool-1-worker-2
任务276开始执行,当前线程名为ForkJoinPool-1-worker-7
任务277开始执行,当前线程名为ForkJoinPool-1-worker-3
任务278开始执行,当前线程名为ForkJoinPool-1-worker-6
任务279开始执行,当前线程名为ForkJoinPool-1-worker-4
任务280开始执行,当前线程名为ForkJoinPool-1-worker-0
任务273执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务279执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务282开始执行,当前线程名为ForkJoinPool-1-worker-4
任务278执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务283开始执行,当前线程名为ForkJoinPool-1-worker-6
任务277执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务284开始执行,当前线程名为ForkJoinPool-1-worker-3
任务276执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务285开始执行,当前线程名为ForkJoinPool-1-worker-7
任务275执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务286开始执行,当前线程名为ForkJoinPool-1-worker-2
任务281开始执行,当前线程名为ForkJoinPool-1-worker-5
任务274执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务287开始执行,当前线程名为ForkJoinPool-1-worker-1
任务280执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务288开始执行,当前线程名为ForkJoinPool-1-worker-0
任务283执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务285执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务289开始执行,当前线程名为ForkJoinPool-1-worker-6
任务281执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务291开始执行,当前线程名为ForkJoinPool-1-worker-5
任务290开始执行,当前线程名为ForkJoinPool-1-worker-7
任务284执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务286执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务293开始执行,当前线程名为ForkJoinPool-1-worker-2
任务282执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务294开始执行,当前线程名为ForkJoinPool-1-worker-4
任务288执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务295开始执行,当前线程名为ForkJoinPool-1-worker-0
任务287执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务296开始执行,当前线程名为ForkJoinPool-1-worker-1
任务292开始执行,当前线程名为ForkJoinPool-1-worker-3
任务291执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务290执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务289执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务298开始执行,当前线程名为ForkJoinPool-1-worker-7
任务297开始执行,当前线程名为ForkJoinPool-1-worker-5
任务299开始执行,当前线程名为ForkJoinPool-1-worker-6
任务294执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务296执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务301开始执行,当前线程名为ForkJoinPool-1-worker-1
任务295执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务300开始执行,当前线程名为ForkJoinPool-1-worker-4
任务302开始执行,当前线程名为ForkJoinPool-1-worker-0
任务292执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务293执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务304开始执行,当前线程名为ForkJoinPool-1-worker-2
任务303开始执行,当前线程名为ForkJoinPool-1-worker-3
任务297执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务305开始执行,当前线程名为ForkJoinPool-1-worker-5
任务298执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务306开始执行,当前线程名为ForkJoinPool-1-worker-7
任务300执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务307开始执行,当前线程名为ForkJoinPool-1-worker-4
任务299执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务308开始执行,当前线程名为ForkJoinPool-1-worker-6
任务303执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务309开始执行,当前线程名为ForkJoinPool-1-worker-3
任务301执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务310开始执行,当前线程名为ForkJoinPool-1-worker-1
任务302执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务304执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务312开始执行,当前线程名为ForkJoinPool-1-worker-2
任务311开始执行,当前线程名为ForkJoinPool-1-worker-0
任务305执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务313开始执行,当前线程名为ForkJoinPool-1-worker-5
任务308执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务309执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务315开始执行,当前线程名为ForkJoinPool-1-worker-3
任务307执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务316开始执行,当前线程名为ForkJoinPool-1-worker-4
任务310执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务312执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务318开始执行,当前线程名为ForkJoinPool-1-worker-2
任务314开始执行,当前线程名为ForkJoinPool-1-worker-6
任务317开始执行,当前线程名为ForkJoinPool-1-worker-1
任务311执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务319开始执行,当前线程名为ForkJoinPool-1-worker-0
任务306执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务320开始执行,当前线程名为ForkJoinPool-1-worker-7
任务313执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务321开始执行,当前线程名为ForkJoinPool-1-worker-5
任务319执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务317执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务322开始执行,当前线程名为ForkJoinPool-1-worker-1
任务323开始执行,当前线程名为ForkJoinPool-1-worker-0
任务314执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务324开始执行,当前线程名为ForkJoinPool-1-worker-6
任务318执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务325开始执行,当前线程名为ForkJoinPool-1-worker-2
任务320执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务326开始执行,当前线程名为ForkJoinPool-1-worker-7
任务315执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务316执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务327开始执行,当前线程名为ForkJoinPool-1-worker-3
任务328开始执行,当前线程名为ForkJoinPool-1-worker-4
任务321执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务329开始执行,当前线程名为ForkJoinPool-1-worker-5
任务324执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务323执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务328执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务327执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务332开始执行,当前线程名为ForkJoinPool-1-worker-3
任务333开始执行,当前线程名为ForkJoinPool-1-worker-4
任务322执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务334开始执行,当前线程名为ForkJoinPool-1-worker-1
任务330开始执行,当前线程名为ForkJoinPool-1-worker-6
任务331开始执行,当前线程名为ForkJoinPool-1-worker-0
任务325执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务335开始执行,当前线程名为ForkJoinPool-1-worker-2
任务326执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务336开始执行,当前线程名为ForkJoinPool-1-worker-7
任务329执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务337开始执行,当前线程名为ForkJoinPool-1-worker-5
任务332执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务338开始执行,当前线程名为ForkJoinPool-1-worker-3
任务335执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务339开始执行,当前线程名为ForkJoinPool-1-worker-2
任务333执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务340开始执行,当前线程名为ForkJoinPool-1-worker-4
任务334执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务341开始执行,当前线程名为ForkJoinPool-1-worker-1
任务330执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务342开始执行,当前线程名为ForkJoinPool-1-worker-6
任务331执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务343开始执行,当前线程名为ForkJoinPool-1-worker-0
任务336执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务344开始执行,当前线程名为ForkJoinPool-1-worker-7
任务337执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务345开始执行,当前线程名为ForkJoinPool-1-worker-5
任务339执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务346开始执行,当前线程名为ForkJoinPool-1-worker-2
任务338执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务347开始执行,当前线程名为ForkJoinPool-1-worker-3
任务340执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务348开始执行,当前线程名为ForkJoinPool-1-worker-4
任务341执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务342执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务349开始执行,当前线程名为ForkJoinPool-1-worker-1
任务350开始执行,当前线程名为ForkJoinPool-1-worker-6
任务343执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务351开始执行,当前线程名为ForkJoinPool-1-worker-0
任务344执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务352开始执行,当前线程名为ForkJoinPool-1-worker-7
任务345执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务353开始执行,当前线程名为ForkJoinPool-1-worker-5
任务349执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务354开始执行,当前线程名为ForkJoinPool-1-worker-1
任务346执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务355开始执行,当前线程名为ForkJoinPool-1-worker-2
任务347执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务356开始执行,当前线程名为ForkJoinPool-1-worker-3
任务351执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务357开始执行,当前线程名为ForkJoinPool-1-worker-0
任务348执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务358开始执行,当前线程名为ForkJoinPool-1-worker-4
任务350执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务359开始执行,当前线程名为ForkJoinPool-1-worker-6
任务352执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务360开始执行,当前线程名为ForkJoinPool-1-worker-7
任务353执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务361开始执行,当前线程名为ForkJoinPool-1-worker-5
任务354执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务355执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务362开始执行,当前线程名为ForkJoinPool-1-worker-1
任务363开始执行,当前线程名为ForkJoinPool-1-worker-2
任务357执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务364开始执行,当前线程名为ForkJoinPool-1-worker-0
任务356执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务359执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务366开始执行,当前线程名为ForkJoinPool-1-worker-6
任务365开始执行,当前线程名为ForkJoinPool-1-worker-3
任务358执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务367开始执行,当前线程名为ForkJoinPool-1-worker-4
任务360执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务368开始执行,当前线程名为ForkJoinPool-1-worker-7
任务361执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务369开始执行,当前线程名为ForkJoinPool-1-worker-5
任务364执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务366执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务370开始执行,当前线程名为ForkJoinPool-1-worker-6
任务371开始执行,当前线程名为ForkJoinPool-1-worker-0
任务362执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务372开始执行,当前线程名为ForkJoinPool-1-worker-1
任务363执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务373开始执行,当前线程名为ForkJoinPool-1-worker-2
任务365执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务374开始执行,当前线程名为ForkJoinPool-1-worker-3
任务367执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务375开始执行,当前线程名为ForkJoinPool-1-worker-4
任务368执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务376开始执行,当前线程名为ForkJoinPool-1-worker-7
任务369执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务377开始执行,当前线程名为ForkJoinPool-1-worker-5
任务371执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务370执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务378开始执行,当前线程名为ForkJoinPool-1-worker-0
任务379开始执行,当前线程名为ForkJoinPool-1-worker-6
任务372执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务373执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务380开始执行,当前线程名为ForkJoinPool-1-worker-1
任务381开始执行,当前线程名为ForkJoinPool-1-worker-2
任务374执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务382开始执行,当前线程名为ForkJoinPool-1-worker-3
任务375执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务383开始执行,当前线程名为ForkJoinPool-1-worker-4
任务376执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务384开始执行,当前线程名为ForkJoinPool-1-worker-7
任务377执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务385开始执行,当前线程名为ForkJoinPool-1-worker-5
任务381执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务378执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务386开始执行,当前线程名为ForkJoinPool-1-worker-2
任务383执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务379执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务380执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务389开始执行,当前线程名为ForkJoinPool-1-worker-1
任务382执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务390开始执行,当前线程名为ForkJoinPool-1-worker-3
任务388开始执行,当前线程名为ForkJoinPool-1-worker-4
任务387开始执行,当前线程名为ForkJoinPool-1-worker-0
任务391开始执行,当前线程名为ForkJoinPool-1-worker-6
任务384执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务392开始执行,当前线程名为ForkJoinPool-1-worker-7
任务385执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务393开始执行,当前线程名为ForkJoinPool-1-worker-5
任务389执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务388执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务387执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务390执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务391执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务398开始执行,当前线程名为ForkJoinPool-1-worker-6
任务397开始执行,当前线程名为ForkJoinPool-1-worker-1
任务396开始执行,当前线程名为ForkJoinPool-1-worker-0
任务394开始执行,当前线程名为ForkJoinPool-1-worker-4
任务395开始执行,当前线程名为ForkJoinPool-1-worker-3
任务386执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务399开始执行,当前线程名为ForkJoinPool-1-worker-2
任务392执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务400开始执行,当前线程名为ForkJoinPool-1-worker-7
任务393执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务401开始执行,当前线程名为ForkJoinPool-1-worker-5
任务397执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务399执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务402开始执行,当前线程名为ForkJoinPool-1-worker-1
任务395执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务404开始执行,当前线程名为ForkJoinPool-1-worker-3
任务394执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务405开始执行,当前线程名为ForkJoinPool-1-worker-4
任务398执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务406开始执行,当前线程名为ForkJoinPool-1-worker-6
任务396执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务407开始执行,当前线程名为ForkJoinPool-1-worker-0
任务403开始执行,当前线程名为ForkJoinPool-1-worker-2
任务400执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务408开始执行,当前线程名为ForkJoinPool-1-worker-7
任务401执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务409开始执行,当前线程名为ForkJoinPool-1-worker-5
任务403执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务410开始执行,当前线程名为ForkJoinPool-1-worker-2
任务402执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务405执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务404执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务413开始执行,当前线程名为ForkJoinPool-1-worker-3
任务411开始执行,当前线程名为ForkJoinPool-1-worker-1
任务406执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务414开始执行,当前线程名为ForkJoinPool-1-worker-6
任务412开始执行,当前线程名为ForkJoinPool-1-worker-4
任务407执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务415开始执行,当前线程名为ForkJoinPool-1-worker-0
任务408执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务416开始执行,当前线程名为ForkJoinPool-1-worker-7
任务409执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务417开始执行,当前线程名为ForkJoinPool-1-worker-5
任务410执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务418开始执行,当前线程名为ForkJoinPool-1-worker-2
任务413执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务419开始执行,当前线程名为ForkJoinPool-1-worker-3
任务415执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务420开始执行,当前线程名为ForkJoinPool-1-worker-0
任务412执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务421开始执行,当前线程名为ForkJoinPool-1-worker-4
任务414执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务422开始执行,当前线程名为ForkJoinPool-1-worker-6
任务411执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务423开始执行,当前线程名为ForkJoinPool-1-worker-1
任务416执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务424开始执行,当前线程名为ForkJoinPool-1-worker-7
任务417执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务425开始执行,当前线程名为ForkJoinPool-1-worker-5
任务422执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务426开始执行,当前线程名为ForkJoinPool-1-worker-6
任务419执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务420执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务421执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务429开始执行,当前线程名为ForkJoinPool-1-worker-4
任务427开始执行,当前线程名为ForkJoinPool-1-worker-3
任务418执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务430开始执行,当前线程名为ForkJoinPool-1-worker-2
任务428开始执行,当前线程名为ForkJoinPool-1-worker-0
任务423执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务431开始执行,当前线程名为ForkJoinPool-1-worker-1
任务424执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务432开始执行,当前线程名为ForkJoinPool-1-worker-7
任务425执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务433开始执行,当前线程名为ForkJoinPool-1-worker-5
任务426执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务434开始执行,当前线程名为ForkJoinPool-1-worker-6
任务427执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务435开始执行,当前线程名为ForkJoinPool-1-worker-3
任务430执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务436开始执行,当前线程名为ForkJoinPool-1-worker-2
任务428执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务437开始执行,当前线程名为ForkJoinPool-1-worker-0
任务429执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务438开始执行,当前线程名为ForkJoinPool-1-worker-4
任务431执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务439开始执行,当前线程名为ForkJoinPool-1-worker-1
任务432执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务440开始执行,当前线程名为ForkJoinPool-1-worker-7
任务433执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务441开始执行,当前线程名为ForkJoinPool-1-worker-5
任务434执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务442开始执行,当前线程名为ForkJoinPool-1-worker-6
任务437执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务443开始执行,当前线程名为ForkJoinPool-1-worker-0
任务435执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务436执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务445开始执行,当前线程名为ForkJoinPool-1-worker-2
任务444开始执行,当前线程名为ForkJoinPool-1-worker-3
任务439执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务446开始执行,当前线程名为ForkJoinPool-1-worker-1
任务438执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务447开始执行,当前线程名为ForkJoinPool-1-worker-4
任务440执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务448开始执行,当前线程名为ForkJoinPool-1-worker-7
任务441执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务449开始执行,当前线程名为ForkJoinPool-1-worker-5
任务442执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务450开始执行,当前线程名为ForkJoinPool-1-worker-6
任务443执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务451开始执行,当前线程名为ForkJoinPool-1-worker-0
任务444执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务452开始执行,当前线程名为ForkJoinPool-1-worker-3
任务446执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务445执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务454开始执行,当前线程名为ForkJoinPool-1-worker-2
任务453开始执行,当前线程名为ForkJoinPool-1-worker-1
任务447执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务455开始执行,当前线程名为ForkJoinPool-1-worker-4
任务448执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务456开始执行,当前线程名为ForkJoinPool-1-worker-7
任务449执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务457开始执行,当前线程名为ForkJoinPool-1-worker-5
任务450执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务458开始执行,当前线程名为ForkJoinPool-1-worker-6
任务451执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务452执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务459开始执行,当前线程名为ForkJoinPool-1-worker-0
任务460开始执行,当前线程名为ForkJoinPool-1-worker-3
任务453执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务461开始执行,当前线程名为ForkJoinPool-1-worker-1
任务455执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务462开始执行,当前线程名为ForkJoinPool-1-worker-4
任务454执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务463开始执行,当前线程名为ForkJoinPool-1-worker-2
任务456执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务464开始执行,当前线程名为ForkJoinPool-1-worker-7
任务457执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务465开始执行,当前线程名为ForkJoinPool-1-worker-5
任务458执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务466开始执行,当前线程名为ForkJoinPool-1-worker-6
任务460执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务467开始执行,当前线程名为ForkJoinPool-1-worker-3
任务459执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务468开始执行,当前线程名为ForkJoinPool-1-worker-0
任务463执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务469开始执行,当前线程名为ForkJoinPool-1-worker-2
任务461执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务470开始执行,当前线程名为ForkJoinPool-1-worker-1
任务462执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务471开始执行,当前线程名为ForkJoinPool-1-worker-4
任务464执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务472开始执行,当前线程名为ForkJoinPool-1-worker-7
任务465执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务473开始执行,当前线程名为ForkJoinPool-1-worker-5
任务466执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务474开始执行,当前线程名为ForkJoinPool-1-worker-6
任务467执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务475开始执行,当前线程名为ForkJoinPool-1-worker-3
任务468执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务476开始执行,当前线程名为ForkJoinPool-1-worker-0
任务469执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务471执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务478开始执行,当前线程名为ForkJoinPool-1-worker-4
任务470执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务479开始执行,当前线程名为ForkJoinPool-1-worker-1
任务477开始执行,当前线程名为ForkJoinPool-1-worker-2
任务472执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务480开始执行,当前线程名为ForkJoinPool-1-worker-7

Process finished with exit code 0

Preste atención a la misma configuración aquí, no hay presión en Apple M1, y la CPU de 8 núcleos en la CPU de Windows se dispara en un 100% ~

¿Por qué usar un grupo de subprocesos en lugar de Thread?

Esta pregunta no tiene sentido para los veteranos, pero los novatos deben prestarle atención. En primer lugar, no niego que no es bueno usar Thread directamente, todo depende todavía de su escenario, si todo su sistema tiene solo uno o algunos hilos, y el tiempo de ejecución es muy corto y el número de ejecuciones es muy pequeño, por supuesto no niego que este no sea el problema, pero si tienes la siguiente situación debes prestar atención.

1. El número de ejecuciones es muy frecuente;

2. Hay muchos lugares para la ejecución;

3. La duración de la ejecución del subproceso es impredecible o muy larga;

Entonces puede ocurrir la siguiente situación:

1. La CPU o la memoria fluctúan y hay una alarma en medio de la noche;

2. A menudo no sé por qué FullGc;

3. El acoplamiento de código no se atreve a cambiar al azar;

4. Hay muchos factores incontrolables, como la memoria siempre está ocupada, la cantidad de subprocesos es demasiado alta y el sistema se congela, por supuesto, hay muchos ~

...

Por lo tanto, los recursos de administración y control unificados (asignación, ajuste y monitoreo) del grupo de subprocesos garantizan hasta cierto punto la estabilidad del sistema.Los puntos principales son los siguientes:

  1. Control de recursos: el grupo de subprocesos puede limitar la cantidad de subprocesos que se ejecutan al mismo tiempo, lo que evita el consumo excesivo de recursos del sistema y provoca fallas en el sistema.

  2. Mejore la eficiencia: el grupo de subprocesos puede reutilizar los subprocesos creados, evitando la sobrecarga de crear y destruir subprocesos con frecuencia, y mejorando la eficiencia de ejecución del programa.

  3. Mejorar la velocidad de respuesta: el grupo de subprocesos puede precrear e inicializar una cierta cantidad de subprocesos, y cuando llega la tarea, se puede ejecutar de inmediato, lo que mejora la velocidad de respuesta del programa.

  4. Programación simplificada: el uso del grupo de subprocesos permite a los programadores centrarse en la implementación de la lógica comercial sin tener que preocuparse por la creación y administración de subprocesos, lo que simplifica el proceso de programación. El uso del grupo de subprocesos puede controlar mejor los recursos del sistema, mejorar la eficiencia y la velocidad de respuesta del programa y simplificar el proceso de programación. Por lo tanto, en la programación de subprocesos múltiples, usar un grupo de subprocesos es una mejor opción.

Aprendizaje del código fuente

marco ejecutor

El marco Executor es un marco para administrar grupos de subprocesos en Java. Proporciona un mecanismo para separar el envío y la ejecución de tareas, de modo que el marco pueda administrar automáticamente la creación y destrucción de subprocesos, lo que reduce la sobrecarga de la creación de subprocesos y el cambio de contexto. Rendimiento mejorado del sistema. El marco Executor incluye principalmente los siguientes tres componentes principales:

  1. Interfaz de ejecución: esta interfaz define un método de ejecución para enviar tareas al grupo de subprocesos para su ejecución.

  2. Interfaz ExecutorService: esta interfaz hereda la interfaz Executor y agrega algunos métodos para administrar grupos de subprocesos, como el método de envío, el método de apagado, etc.

  3. Clase ThreadPoolExecutor: esta clase es la clase de implementación del grupo de subprocesos, que proporciona una gran cantidad de configuraciones de parámetros y puede crear diferentes grupos de subprocesos según las diferentes necesidades. Por ejemplo, se pueden establecer parámetros como la cantidad de subprocesos principales, la cantidad máxima de subprocesos, la capacidad de la cola y las políticas de rechazo. El uso del marco Executor puede realizar fácilmente la creación y administración del grupo de subprocesos y mejorar el rendimiento y la estabilidad del sistema. Al mismo tiempo, el marco Executor también proporciona algunas clases de herramientas convenientes, como la clase Executors y la interfaz ScheduledExecutorService, que pueden implementar funciones como tareas programadas, tareas retrasadas y tareas periódicas, que son muy adecuadas para la programación de subprocesos múltiples. y procesamiento concurrente.

92b951a87cf67f9313e87c9e5f7795b2.png

java.util.concurrent.Executor

//该接口定义了线程池的基本执行方法
public interface Executor {

    //在将来的某个时间执行给定的命令。该命令可以在新线程、池线程或调用线程中执行,由Executor实现自行决定。Params: command -可运行任务抛出:RejectedExecutionException -如果该任务不能被接受执行NullPointerException -如果命令为空
    void execute(Runnable command);
}

java.util.concurrent.ExecutorService

/**
 * @author: csh
 * @Date: 2023/3/7 23:08
 * @Description:
 */
public interface ExecutorServiceStudy {

    /**
     * shutdown方法用于关闭线程池,不会立即停止所有任务的执行,而是等待所有任务执行完毕后再关闭。
     */
    void shutdown();

    /**
     * shutdownNow方法用于关闭线程池,并尝试停止所有正在执行的任务。
     */
    List<Runnable> shutdownNow();

    /**
     * isShutdown方法用于判断线程池是否已经关闭。
     */
    boolean isShutdown();

    /**
     * isTerminated方法用于判断线程池是否已经关闭,并且所有任务都已经执行完毕。
     */
    boolean isTerminated();

    /**
     * awaitTermination方法用于等待线程池关闭,并且所有任务都已经执行完毕。
     */
    boolean awaitTermination(long timeout, TimeUnit unit)
            throws InterruptedException;

    /**
     * submit方法用于提交一个Callable或Runnable任务到线程池,并返回一个Future对象,可以通过Future对象获取任务的执行结果或取消任务的执行。
     */
    <T> Future<T> submit(Callable<T> task);

    /**
     * Submits提交一个可运行任务以供执行,并返回表示该任务的Future。Future的get方法将在成功完成时返回给定的结果。
     */
    <T> Future<T> submit(Runnable task, T result);

    /**
     * 提交一个可运行任务以供执行,并返回表示该任务的Future。Future的get方法将在成功完成时返回null。
     */
    Future<?> submit(Runnable task);

    /**
     * 执行给定的任务,在所有任务完成时返回包含它们的状态和结果的Futures列表。的未来。对于返回列表的每个元素,isDone都是true。
     */
    <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
            throws InterruptedException;

    /**
     * 带超时时间 同上类似
     */
    <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
                                  long timeout, TimeUnit unit)
            throws InterruptedException;

    /**
     * 执行给定的任务,如果有成功完成的任务,则返回成功完成的任务的结果(即,没有抛出异常)。在正常或异常返回时,未完成的任务将被取消。如果在执行此操作时修改了给定的集合,则此方法的结果是未定义的。
     */
    <T> T invokeAny(Collection<? extends Callable<T>> tasks)
            throws InterruptedException, ExecutionException;

    /**
     * 同上类似 带超时时间
     */
    <T> T invokeAny(Collection<? extends Callable<T>> tasks,
                    long timeout, TimeUnit unit)
            throws InterruptedException, ExecutionException, TimeoutException;
}

java.util.concurrent.AbstractExecutorService

package java.util.concurrent;
import java.util.*;
//提供ExecutorService执行方法的默认实现。该类是一个抽象类仅供继承
public abstract class AbstractExecutorService implements ExecutorService {

    //为给定的可运行对象和默认值返回一个RunnableFuture。
    protected <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) {
        return new FutureTask<T>(runnable, value);
    }

    //同上
    protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
        return new FutureTask<T>(callable);
    }

    //任务提交
    public Future<?> submit(Runnable task) {
        if (task == null) throw new NullPointerException();
        //创建RunnableFuture
        RunnableFuture<Void> ftask = newTaskFor(task, null);
        //执行
        execute(ftask);
        //返回
        return ftask;
    }

    //任务提交
    //task为任务
    //result 为自定义返回结果
    public <T> Future<T> submit(Runnable task, T result) {
        if (task == null) throw new NullPointerException();
        RunnableFuture<T> ftask = newTaskFor(task, result);
        execute(ftask);
        return ftask;
    }

    //任务提交的方法
    public <T> Future<T> submit(Callable<T> task) {
        if (task == null) throw new NullPointerException();
        RunnableFuture<T> ftask = newTaskFor(task);
        execute(ftask);
        return ftask;
    }

    /**
     * 该方法是实现唤醒任意一个方法
     */
    private <T> T doInvokeAny(Collection<? extends Callable<T>> tasks,
                              boolean timed, long nanos)
        throws InterruptedException, ExecutionException, TimeoutException {
        if (tasks == null)
            throw new NullPointerException();
            //获取长度
        int ntasks = tasks.size();
        //为0抛出异常
        if (ntasks == 0)
            throw new IllegalArgumentException();
        //创建阶列
        ArrayList<Future<T>> futures = new ArrayList<Future<T>>(ntasks);
        //这里一个
        ExecutorCompletionService<T> ecs =
            new ExecutorCompletionService<T>(this);

        // For efficiency, especially in executors with limited
        // parallelism, check to see if previously submitted tasks are
        // done before submitting more of them. This interleaving
        // plus the exception mechanics account for messiness of main
        // loop.

        try {
            // Record exceptions so that if we fail to obtain any
            // result, we can throw the last exception we got.
            ExecutionException ee = null;
            final long deadline = timed ? System.nanoTime() + nanos : 0L;
            Iterator<? extends Callable<T>> it = tasks.iterator();

            // Start one task for sure; the rest incrementally
            //确定开始的任务
            futures.add(ecs.submit(it.next()));
            --ntasks;//递减
            int active = 1;
            //循环调用
            for (;;) {
                //获取队列的头,如果没有为null (阻塞队列)
                Future<T> f = ecs.poll();
                //为空
                if (f == null) {
                    //如果大于0
                    if (ntasks > 0) {
                        --ntasks;
                        //指向下一个节点
                        futures.add(ecs.submit(it.next()));
                        ++active;
                    }
                    //为0 最后一个了,跳出
                    else if (active == 0)
                        break;
                    //其他逻辑 传进来timed 为true 进行超时时间判断和计算
                    else if (timed) {
                        f = ecs.poll(nanos, TimeUnit.NANOSECONDS);
                        if (f == null)
                            throw new TimeoutException();
                        nanos = deadline - System.nanoTime();
                    }
                    //所有都没有 检索并删除表示下一个已完成任务的Future,如果没有则等待。
                    else
                        f = ecs.take();
                }
                //如果不为空
                if (f != null) {
                    //自减 
                    --active;
                    try {
                        //返回 这里如果获取异常下面做了处理
                        return f.get();
                    } catch (ExecutionException eex) {
                        ee = eex;
                    } catch (RuntimeException rex) {
                        ee = new ExecutionException(rex);
                    }
                }
            }
            //如果异常类型为空 进行初始化
            if (ee == null)
                ee = new ExecutionException();
            //然后抛出
            throw ee;

        } finally {
            //最后做下 所有任务的取消
            for (int i = 0, size = futures.size(); i < size; i++)
                futures.get(i).cancel(true);
        }
    }
    //调用以上的方法
    public <T> T invokeAny(Collection<? extends Callable<T>> tasks)
        throws InterruptedException, ExecutionException {
        try {
            return doInvokeAny(tasks, false, 0);
        } catch (TimeoutException cannotHappen) {
            assert false;
            return null;
        }
    }
    //带过期时间的调用任意一个任务
    public <T> T invokeAny(Collection<? extends Callable<T>> tasks,
                           long timeout, TimeUnit unit)
        throws InterruptedException, ExecutionException, TimeoutException {
        return doInvokeAny(tasks, true, unit.toNanos(timeout));
    }
    //调用所有任务
    public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
        throws InterruptedException {
        if (tasks == null)
            throw new NullPointerException();
        ArrayList<Future<T>> futures = new ArrayList<Future<T>>(tasks.size());
        boolean done = false;
        try {
            for (Callable<T> t : tasks) {
                //注意这个RunnableFuture 是runnable和future的结合体,用于表示一个异步任务的结果
                RunnableFuture<T> f = newTaskFor(t);
                futures.add(f);
                //执行
                execute(f);
            }
            for (int i = 0, size = futures.size(); i < size; i++) {
                Future<T> f = futures.get(i);
                if (!f.isDone()) {
                    try {
                        f.get();
                    } catch (CancellationException ignore) {
                    } catch (ExecutionException ignore) {
                    }
                }
            }
            done = true;
            return futures;
        } finally {
            if (!done)
                for (int i = 0, size = futures.size(); i < size; i++)
                    futures.get(i).cancel(true);
        }
    }
    //带过期时间调用所有任务
    public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
                                         long timeout, TimeUnit unit)
        throws InterruptedException {
        if (tasks == null)
            throw new NullPointerException();
        long nanos = unit.toNanos(timeout);
        ArrayList<Future<T>> futures = new ArrayList<Future<T>>(tasks.size());
        boolean done = false;
        try {
            for (Callable<T> t : tasks)
                futures.add(newTaskFor(t));

            final long deadline = System.nanoTime() + nanos;
            final int size = futures.size();

            // Interleave time checks and calls to execute in case
            // executor doesn't have any/much parallelism.
            for (int i = 0; i < size; i++) {
                execute((Runnable)futures.get(i));
                nanos = deadline - System.nanoTime();
                if (nanos <= 0L)
                    return futures;
            }

            for (int i = 0; i < size; i++) {
                Future<T> f = futures.get(i);
                if (!f.isDone()) {
                    if (nanos <= 0L)
                        return futures;
                    try {
                        f.get(nanos, TimeUnit.NANOSECONDS);
                    } catch (CancellationException ignore) {
                    } catch (ExecutionException ignore) {
                    } catch (TimeoutException toe) {
                        return futures;
                    }
                    nanos = deadline - System.nanoTime();
                }
            }
            done = true;
            return futures;
        } finally {
            if (!done)
                for (int i = 0, size = futures.size(); i < size; i++)
                    futures.get(i).cancel(true);
        }
    }

}

La implementación del método proporcionado en AbstractExecutorService incluye los siguientes aspectos:

  1. Método newTaskFor(): este método se usa para crear un objeto RunnableFuture, que es una combinación de Future y Runnable, y se puede usar para representar el resultado de la ejecución de una tarea asíncrona. En AbstractExecutorService, la implementación predeterminada de este método es usar la clase FutureTask para crear un objeto RunnableFuture. Si necesita usar otras implementaciones, puede anular este método en una subclase.

  2. Método de envío (): este método se define en la interfaz ExecutorService y se usa para enviar una tarea al grupo de subprocesos para su ejecución. En AbstractExecutorService, se proporcionan dos tipos de métodos de envío de tareas, Runnable y Callable.Todos ellos llaman al método newTaskFor() para crear un objeto RunnableFuture y entregarlo al método execute() para su ejecución. Si necesita implementar una lógica de envío de tareas personalizada, puede anular este método en una subclase. Cabe señalar que AbstractExecutorService es una clase abstracta y no se puede usar directamente. Es necesario implementar un grupo de subprocesos personalizado heredando esta clase e implementando otros métodos.

java.util.concurrent.FutureTask

Esta es una clase básica.

descripción del estado del estado:

  1. NUEVO: Estado inicial, que indica que se ha creado el objeto FutureTask, pero la tarea aún no ha comenzado a ejecutarse.

  2. COMPLETANDO: Indica que la tarea ha sido ejecutada, pero el resultado no ha sido configurado en FutureTask.

  3. NORMAL: Indica que la tarea se ejecutó con éxito y el resultado se ha configurado en FutureTask.

  4. EXCEPCIONAL: indica que se lanzó una excepción durante la ejecución de la tarea y la información de la excepción se configuró en FutureTask.

  5. CANCELADO: Indica que la tarea ha sido cancelada.

  6. INTERRUMPIENDO: Indica que la tarea está siendo interrumpida.

  7. INTERRUMPIDO: Indica que la tarea ha sido interrumpida.

package java.util.concurrent;
import java.util.concurrent.locks.LockSupport;
//一个可取消的异步计算。
//这里要注意一下,这个是实现了RunnableFuture 而RunnableFuture是 继承了:Runnable, Future<V>
public class FutureTask<V> implements RunnableFuture<V> {


    /**
     * The run state of this task, initially NEW. The run state
     * transitions to a terminal state only in methods set,
     * setException, and cancel. During completion, state may take on
     * transient values of COMPLETING (while outcome is being set) or
     * INTERRUPTING (only while interrupting the runner to satisfy a
     * cancel(true)). Transitions from these intermediate to final
     * states use cheaper ordered/lazy writes because values are unique
     * and cannot be further modified.
     *
     * Possible state transitions:
     * NEW -> COMPLETING -> NORMAL
     * NEW -> COMPLETING -> EXCEPTIONAL
     * NEW -> CANCELLED
     * NEW -> INTERRUPTING -> INTERRUPTED
     */
    //状态 可能的状态转换:NEW -> completion -> NORMAL NEW -> completion -> exception NEW -> CANCELLED NEW -> INTERRUPTED -> INTERRUPTED
    private volatile int state;
    //实始化状态
    private static final int NEW = 0;
    /**
NEW:初始状态,表示FutureTask对象已经创建,但任务还没有开始执行。
COMPLETING:表示任务已经执行完成,但还没有将结果设置到FutureTask中。
NORMAL:表示任务执行成功,并且已经将结果设置到FutureTask中。
EXCEPTIONAL:表示任务执行过程中抛出了异常,并且已经将异常信息设置到FutureTask中。
CANCELLED:表示任务已经被取消。
INTERRUPTING:表示任务正在被中断。
INTERRUPTED:表示任务已经被中断。
    **/
    private static final int COMPLETING = 1;
    private static final int NORMAL = 2;
    private static final int EXCEPTIONAL = 3;
    private static final int CANCELLED = 4;
    private static final int INTERRUPTING = 5;
    private static final int INTERRUPTED = 6;

    /** 调用的对象 ,运行后为空 */
    private Callable<V> callable;
    /**要返回的结果或跑出的异常 */
    private Object outcome; // non-volatile, protected by state reads/writes
    /** 运行可调用对象的线程;在run()期间进行case */
    private volatile Thread runner;
    /** 等待线程的Treiber堆栈 */
    private volatile WaitNode waiters;

    //返回已完成任务的结果或抛出异常。完成状态值
    @SuppressWarnings("unchecked")
    private V report(int s) throws ExecutionException {
        Object x = outcome;
        if (s == NORMAL)
            return (V)x;
        if (s >= CANCELLED)
            throw new CancellationException();
        throw new ExecutionException((Throwable)x);
    }

    //构造方法
    public FutureTask(Callable<V> callable) {
        if (callable == null)
            throw new NullPointerException();
        this.callable = callable;
        this.state = NEW; // ensure visibility of callable
    }

   //构造方法
    public FutureTask(Runnable runnable, V result) {
        this.callable = Executors.callable(runnable, result);
        this.state = NEW; // ensure visibility of callable
    }
    //判断是否取消
    public boolean isCancelled() {
        return state >= CANCELLED;
    }
    //判断是否已完成
    public boolean isDone() {
        return state != NEW;
    }
    //取消方法
    public boolean cancel(boolean mayInterruptIfRunning) {
        //状态不为初始 且
        if (!(state == NEW && cas锁获取成功 返回 false
              UNSAFE.compareAndSwapInt(this, stateOffset, NEW,
                  mayInterruptIfRunning ? INTERRUPTING : CANCELLED)))
            return false;
        try { // in case call to interrupt throws exception
            if (mayInterruptIfRunning) {
                try {
                    Thread t = runner;
                    //不为空进行中断
                    if (t != null)
                        t.interrupt();
                } finally { // final state
                    //更新状态
                    UNSAFE.putOrderedInt(this, stateOffset, INTERRUPTED);
                }
            }
        } finally {
            //删除并通知所有等待线程,调用done(),并空出可调用对象。
            finishCompletion();
        }
        //返回成功
        return true;
    }

    //获取线程
    public V get() throws InterruptedException, ExecutionException {
        int s = state;
        if (s <= COMPLETING)
            s = awaitDone(false, 0L);
        return report(s);
    }

    //带超时时间 获取
    public V get(long timeout, TimeUnit unit)
        throws InterruptedException, ExecutionException, TimeoutException {
        if (unit == null)
            throw new NullPointerException();
        int s = state;
        if (s <= COMPLETING &&
            (s = awaitDone(true, unit.toNanos(timeout))) <= COMPLETING)
            throw new TimeoutException();
        return report(s);
    }

    ///重写方法
    protected void done() { }

    //设置结果为指定值
    protected void set(V v) {
        if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {
            outcome = v;
            UNSAFE.putOrderedInt(this, stateOffset, NORMAL); // final state
            finishCompletion();
        }
    }

    //设置结果 出异常
    protected void setException(Throwable t) {
        if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {
            outcome = t;
            UNSAFE.putOrderedInt(this, stateOffset, EXCEPTIONAL); // final state
            finishCompletion();
        }
    }
    //运行方法
    public void run() {
        if (state != NEW ||
            !UNSAFE.compareAndSwapObject(this, runnerOffset,
                                         null, Thread.currentThread()))
            return;
        try {
            Callable<V> c = callable;
            if (c != null && state == NEW) {
                V result;
                boolean ran;
                try {
                    result = c.call();
                    ran = true;
                } catch (Throwable ex) {
                    result = null;
                    ran = false;
                    setException(ex);
                }
                if (ran)
                    set(result);
            }
        } finally {
            // runner must be non-null until state is settled to
            // prevent concurrent calls to run()
            runner = null;
            // state must be re-read after nulling runner to prevent
            // leaked interrupts
            int s = state;
            if (s >= INTERRUPTING)
                handlePossibleCancellationInterrupt(s);
        }
    }

    //执行不进行设置结果
    protected boolean runAndReset() {
        if (state != NEW ||
            !UNSAFE.compareAndSwapObject(this, runnerOffset,
                                         null, Thread.currentThread()))
            return false;
        boolean ran = false;
        int s = state;
        try {
            Callable<V> c = callable;
            if (c != null && s == NEW) {
                try {
                    c.call(); // don't set result
                    ran = true;
                } catch (Throwable ex) {
                    setException(ex);
                }
            }
        } finally {
            // runner must be non-null until state is settled to
            // prevent concurrent calls to run()
            runner = null;
            // state must be re-read after nulling runner to prevent
            // leaked interrupts
            s = state;
            if (s >= INTERRUPTING)
                handlePossibleCancellationInterrupt(s);
        }
        return ran && s == NEW;
    }

    //确保任何来自可能的取消(true)的中断只在运行或runAndReset时传递给任务。
    private void handlePossibleCancellationInterrupt(int s) {
        // It is possible for our interrupter to stall before getting a
        // chance to interrupt us. Let's spin-wait patiently.
        if (s == INTERRUPTING)
            while (state == INTERRUPTING)
                Thread.yield(); // wait out pending interrupt

        // assert state == INTERRUPTED;

        // We want to clear any interrupt we may have received from
        // cancel(true). However, it is permissible to use interrupts
        // as an independent mechanism for a task to communicate with
        // its caller, and there is no way to clear only the
        // cancellation interrupt.
        //
        // Thread.interrupted();
    }

    //在Treiber堆栈中记录等待线程的简单链表节点。
    static final class WaitNode {
        volatile Thread thread;
        volatile WaitNode next;
        WaitNode() { thread = Thread.currentThread(); }
    }

   //删除并通知所有等待线程,调用done(),并空出可调用对象。
    private void finishCompletion() {
        // assert state > COMPLETING;
        for (WaitNode q; (q = waiters) != null;) {
            if (UNSAFE.compareAndSwapObject(this, waitersOffset, q, null)) {
                for (;;) {
                    Thread t = q.thread;
                    if (t != null) {
                        q.thread = null;
                        LockSupport.unpark(t);
                    }
                    WaitNode next = q.next;
                    if (next == null)
                        break;
                    q.next = null; // unlink to help gc
                    q = next;
                }
                break;
            }
        }

        done();

        callable = null; // to reduce footprint
    }

    //在中断或超时时等待完成或中止
    private int awaitDone(boolean timed, long nanos)
        throws InterruptedException {
        final long deadline = timed ? System.nanoTime() + nanos : 0L;
        WaitNode q = null;
        boolean queued = false;
        for (;;) {
            if (Thread.interrupted()) {
                removeWaiter(q);
                throw new InterruptedException();
            }

            int s = state;
            if (s > COMPLETING) {
                if (q != null)
                    q.thread = null;
                return s;
            }
            else if (s == COMPLETING) // cannot time out yet
                Thread.yield();
            else if (q == null)
                q = new WaitNode();
            else if (!queued)
                queued = UNSAFE.compareAndSwapObject(this, waitersOffset,
                                                     q.next = waiters, q);
            else if (timed) {
                nanos = deadline - System.nanoTime();
                if (nanos <= 0L) {
                    removeWaiter(q);
                    return state;
                }
                LockSupport.parkNanos(this, nanos);
            }
            else
                LockSupport.park(this);
        }
    }

    //尝试断开超时或中断的等待节点的链接,以避免累积垃圾。
    private void removeWaiter(WaitNode node) {
        if (node != null) {
            node.thread = null;
            retry:
            for (;;) { // restart on removeWaiter race
                for (WaitNode pred = null, q = waiters, s; q != null; q = s) {
                    s = q.next;
                    if (q.thread != null)
                        pred = q;
                    else if (pred != null) {
                        pred.next = s;
                        if (pred.thread == null) // check for race
                            continue retry;
                    }
                    else if (!UNSAFE.compareAndSwapObject(this, waitersOffset,
                                                          q, s))
                        continue retry;
                }
                break;
            }
        }
    }
    //已下是初始化的信息
    // Unsafe mechanics
    private static final sun.misc.Unsafe UNSAFE;
    private static final long stateOffset;
    private static final long runnerOffset;
    private static final long waitersOffset;
    static {
        try {
            UNSAFE = sun.misc.Unsafe.getUnsafe();
            Class<?> k = FutureTask.class;
            stateOffset = UNSAFE.objectFieldOffset
                (k.getDeclaredField("state"));
            runnerOffset = UNSAFE.objectFieldOffset
                (k.getDeclaredField("runner"));
            waitersOffset = UNSAFE.objectFieldOffset
                (k.getDeclaredField("waiters"));
        } catch (Exception e) {
            throw new Error(e);
        }
    }

}

java.util.concurrent.ThreadPoolExecutor

Este es el aprendizaje de la clase principal, la implementación del conjunto de subprocesos principales.

package java.util.concurrent;

import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.*;
//一种执行程序服务,它使用可能有多个池化线程之一执行每个提交的任务,通常使用执行程序工厂方法进行配置。
//线程池解决了两个不同的问题:由于减少了每个任务的调用开销,它们通常在执行大量异步任务时提供改进的性能,并且它们提供了一种绑定和管理执行任务集合时消耗的资源(包括线程)的方法。
public class ThreadPoolExecutor extends AbstractExecutorService {
    //主池控制状态 ctl,是一个原子整数,包含两个概念字段 workerCount,指示线程运行状态的有效数量,指示是否正在运行、关闭等 为了将它们打包到一个 int 中,我们将 workerCount 限制为 (2^29)-1(约 5 亿)线程,而不是 (2^31)-1(20 亿)否则可表示。
    /* 相关方法:
           runStateOf:获取运行状态;
           workerCountOf:获取活动线程数;
           ctlOf:获取运行状态和活动线程数的值。
    */
    private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
    private static final int COUNT_BITS = Integer.SIZE - 3;
    private static final int CAPACITY = (1 << COUNT_BITS) - 1;

    //以下是高位的状态
    //高3位为111 线程池正在运行,可以接受新的任务。以及对已添加的任务进行处理。
    private static final int RUNNING = -1 << COUNT_BITS;
    //高3位为000 线程池正在关闭,不再接受新的任务,但会继续处理已经提交的任务。
    private static final int SHUTDOWN = 0 << COUNT_BITS;
    //高3位为001 线程池已经停止,不再接受新的任务,也不会处理已经提交的任务,并且会中断正在执行的任务。
    private static final int STOP = 1 << COUNT_BITS;
    //高3位为010 所有的任务都已经终止,线程数量为 0,即将进入 TERMINATED 状态。
    private static final int TIDYING = 2 << COUNT_BITS;
    //高3位为011 线程池已经终止,不再接受新的任务。
    private static final int TERMINATED = 3 << COUNT_BITS;

    // Packing and unpacking ctl
    //获取运行状态
    private static int runStateOf(int c)     { return c & ~CAPACITY; }
    //获取活动线程数
    private static int workerCountOf(int c)  { return c & CAPACITY; }
    //获取运行状态和活动线程数的值
    private static int ctlOf(int rs, int wc) { return rs | wc; }

    //用于判断 c是否小于s 一般用于状态判断
    private static boolean runStateLessThan(int c, int s) {
        return c < s;
    }
    //用于判断 c大于等于s
    private static boolean runStateAtLeast(int c, int s) {
        return c >= s;
    }
    //判断是否正在运行
    private static boolean isRunning(int c) {
        return c < SHUTDOWN;
    }

    //cas方式进行状态递增
    private boolean compareAndIncrementWorkerCount(int expect) {
        return ctl.compareAndSet(expect, expect + 1);
    }

    //cas方式状态递减
    private boolean compareAndDecrementWorkerCount(int expect) {
        return ctl.compareAndSet(expect, expect - 1);
    }

    //用于线程突然中断调用
    private void decrementWorkerCount() {
        do {} while (! compareAndDecrementWorkerCount(ctl.get()));
    }

    //用于保存任务和移交给工作线程的队列。
    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;

    /**
     * 如果为 false(默认值),则核心线程即使在空闲时也保持活动状态。如果为 true,则核心线程使用 keepAliveTime 来超时等待工作。
     */
    private volatile boolean allowCoreThreadTimeOut;

    /**
     * 线程池核心线程数量,即使线程处于空闲状态,也不会被回收。
     */
    private volatile int corePoolSize;

    /**
     * 线程池最大线程数量,当工作队列已满且当前线程数小于最大线程数时,会创建新的线程来处理任务。
     */
    private volatile int maximumPoolSize;

    /**
     * 默认的拒绝策略
     */
    private static final RejectedExecutionHandler defaultHandler =
        new AbortPolicy();

    /**
     * 关闭和关闭现在的调用方所需的权限。
     */
    private static final RuntimePermission shutdownPerm =
        new RuntimePermission("modifyThread");

    /*执行终结器时要使用的上下文 */
    private final AccessControlContext acc;

    /**
     * Class Worker 主要维护运行任务的线程的中断控制状态,以及其他次要簿记。
     */
    private final class Worker
        extends AbstractQueuedSynchronizer
        implements Runnable
    {
        /**
         * This class will never be serialized, but we provide a
         * serialVersionUID to suppress a javac warning.
         */
        private static final long serialVersionUID = 6138294804551838833L;

        /** 工作线程 */
        final Thread thread;
        /** 工作线程需要执行的第一个任务,通常是从工作队列中取出来的。默认为空 */
        Runnable firstTask;
        /** 线程的计数器*/
        volatile long completedTasks;

        /**
         *构造方法
         */
        Worker(Runnable firstTask) {
            //
            setState(-1); // 禁止中断
            this.firstTask = firstTask;
            //初始化一个工作线程
            this.thread = getThreadFactory().newThread(this);
        }

        /* 执行 */
        public void run() {
            runWorker(this);
        }

        // Lock methods
        //
        // The value 0 represents the unlocked state.
        // The value 1 represents the locked state.
        //判断是否已加锁 true为是 false 否
        protected boolean isHeldExclusively() {
            return getState() != 0;
        }
        //尝试获取锁
        protected boolean tryAcquire(int unused) {
            if (compareAndSetState(0, 1)) {
                setExclusiveOwnerThread(Thread.currentThread());
                return true;
            }
            return false;
        }
        //尝试释放锁
        protected boolean tryRelease(int unused) {
            setExclusiveOwnerThread(null);
            setState(0);
            return true;
        }
        //加锁
        public void lock()        { acquire(1); }
        //尝试加锁
        public boolean tryLock()  { return tryAcquire(1); }
        //解锁
        public void unlock()      { release(1); }
        //判断是否锁住方法 true为是 false为否
        public boolean isLocked() { return isHeldExclusively(); }
        //中断方法
        void interruptIfStarted() {
            Thread t;
            if (getState() >= 0 && (t = thread) != null && !t.isInterrupted()) {
                try {
                    t.interrupt();
                } catch (SecurityException ignore) {
                }
            }
        }
    }

    /*
     * Methods for setting control state
     */

    //转换指定状态
    private void advanceRunState(int targetState) {
        for (;;) {
            int c = ctl.get();
            if (runStateAtLeast(c, targetState) ||
                ctl.compareAndSet(c, ctlOf(targetState, workerCountOf(c))))
                break;
        }
    }

    //如果(关闭且池和队列为空)或(停止且池为空),则转换为终止状态。
    final void tryTerminate() {
        for (;;) {
            int c = ctl.get();
            //判断是否运行 或 结束状态 或 (关闭且死亡) 则直接返回
            if (isRunning(c) ||
                runStateAtLeast(c, TIDYING) ||
                (runStateOf(c) == SHUTDOWN && ! workQueue.isEmpty()))
                return;
            //非终止,则直接终止
            if (workerCountOf(c) != 0) { // Eligible to terminate
                interruptIdleWorkers(ONLY_ONE);
                return;
            }
            //上锁(重入锁)
            final ReentrantLock mainLock = this.mainLock;
            mainLock.lock();
            try {
                //cas锁
                if (ctl.compareAndSet(c, ctlOf(TIDYING, 0))) {
                    try {
                        //中断
                        terminated();
                    } finally {
                        //最终设置状态
                        ctl.set(ctlOf(TERMINATED, 0));
                        termination.signalAll();
                    }
                    return;
                }
            } finally {
                //解锁
                mainLock.unlock();
            }
            // else retry on failed CAS
        }
    }

    /*
     * Methods for controlling interrupts to worker threads.
     */

    //如果有安全管理器,请确保调用方通常有权关闭线程
    private void checkShutdownAccess() {
        SecurityManager security = System.getSecurityManager();
        if (security != null) {
            security.checkPermission(shutdownPerm);
            final ReentrantLock mainLock = this.mainLock;
            mainLock.lock();
            try {
                for (Worker w : workers)
                    security.checkAccess(w.thread);
            } finally {
                mainLock.unlock();
            }
        }
    }

    /**
     * 中断所有线程方法
     */
    private void interruptWorkers() {
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            for (Worker w : workers)
                w.interruptIfStarted();
        } finally {
            mainLock.unlock();
        }
    }

    /**
     * 中断可能正在等待任务的线程
     */
    private void interruptIdleWorkers(boolean onlyOne) {
        //重入锁
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            for (Worker w : workers) {
                Thread t = w.thread;
                if (!t.isInterrupted() && w.tryLock()) {
                    try {
                        t.interrupt();
                    } catch (SecurityException ignore) {
                    } finally {
                        w.unlock();
                    }
                }
                if (onlyOne)
                    break;
            }
        } finally {
            //解锁
            mainLock.unlock();
        }
    }

   //中断所有线程方法
    private void interruptIdleWorkers() {
        interruptIdleWorkers(false);
    }

    private static final boolean ONLY_ONE = true;

    /*
     * Misc utilities, most of which are also exported to
     * ScheduledThreadPoolExecutor
     */

    /**
     * 调用给定命令的拒绝执行处理程序。
     */
    final void reject(Runnable command) {
        handler.rejectedExecution(command, this);
    }

    /**
     * 关闭方法(空实现)
     */
    void onShutdown() {
    }

    /**
     * 判断关机或启动的方法
     */
    final boolean isRunningOrShutdown(boolean shutdownOK) {
        int rs = runStateOf(ctl.get());
        return rs == RUNNING || (rs == SHUTDOWN && shutdownOK);
    }

    /**
        将任务挪到新表中
     */
    private List<Runnable> drainQueue() {
        BlockingQueue<Runnable> q = workQueue;
        ArrayList<Runnable> taskList = new ArrayList<Runnable>();
        q.drainTo(taskList);
        if (!q.isEmpty()) {
            for (Runnable r : q.toArray(new Runnable[0])) {
                if (q.remove(r))
                    taskList.add(r);
            }
        }
        return taskList;
    }

    /*
     * Methods for creating, running and cleaning up after workers
     */

    /**
     * 检查是否可以根据当前池状态和给定边界(核心或最大)添加新工作线程。
     */
    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 &&
                ! (rs == SHUTDOWN &&
                   firstTask == null &&
                   ! workQueue.isEmpty()))
                return false;

            for (;;) {
                int wc = workerCountOf(c);
                if (wc >= CAPACITY ||
                    wc >= (core ? corePoolSize : maximumPoolSize))
                    return false;
                if (compareAndIncrementWorkerCount(c))
                    break retry;
                c = ctl.get(); // Re-read ctl
                if (runStateOf(c) != rs)
                    continue retry;
                // else CAS failed due to workerCount change; retry inner loop
            }
        }

        boolean workerStarted = false;
        boolean workerAdded = false;
        Worker w = null;
        try {
            w = new Worker(firstTask);
            final Thread t = w.thread;
            if (t != 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 ||
                        (rs == SHUTDOWN && firstTask == null)) {
                        if (t.isAlive()) // precheck that t is startable
                            throw new IllegalThreadStateException();
                        workers.add(w);
                        int s = workers.size();
                        if (s > largestPoolSize)
                            largestPoolSize = s;
                        workerAdded = true;
                    }
                } finally {
                    mainLock.unlock();
                }
                if (workerAdded) {
                    t.start();
                    workerStarted = true;
                }
            }
        } finally {
            if (! workerStarted)
                addWorkerFailed(w);
        }
        return workerStarted;
    }

    /**
     * 用于工作线程回滚的方法
     */
    private void addWorkerFailed(Worker w) {
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            if (w != null)
                workers.remove(w);
            decrementWorkerCount();
            tryTerminate();
        } finally {
            mainLock.unlock();
        }
    }

    //从队列中删除线程
    private void processWorkerExit(Worker w, boolean completedAbruptly) {
        if (completedAbruptly) // If abrupt, then workerCount wasn't adjusted
            decrementWorkerCount();

        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            completedTaskCount += w.completedTasks;
            workers.remove(w);
        } finally {
            mainLock.unlock();
        }

        tryTerminate();

        int c = ctl.get();
        if (runStateLessThan(c, STOP)) {
            if (!completedAbruptly) {
                int min = allowCoreThreadTimeOut ? 0 : corePoolSize;
                if (min == 0 && ! workQueue.isEmpty())
                    min = 1;
                if (workerCountOf(c) >= min)
                    return; // replacement not needed
            }
            addWorker(null, false);
        }
    }

    //获取一个任务
    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())) {
                decrementWorkerCount();
                return null;
            }

            int wc = workerCountOf(c);

            // Are workers subject to culling?
            boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;

            if ((wc > maximumPoolSize || (timed && timedOut))
                && (wc > 1 || workQueue.isEmpty())) {
                if (compareAndDecrementWorkerCount(c))
                    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;
            }
        }
    }

    /**
     * 主工作线程运行循环
     *
     * 1.我们可能会从初始任务开始,在这种情况下,我们不需要获得第一个任务。
     *
     * 2.在运行任何任务之前,获取锁以防止在执行任务时发生其他池中断,然后我们确保除非池停止,否则该线程没有设置其中断。
     *
     * 3. Each task run is preceded by a call to beforeExecute, which
     * might throw an exception, in which case we cause thread to die
     * (breaking loop with completedAbruptly true) without processing
     * the task.
     *
     * 4.任务完成进行收集任务的处理
     *
     * 5. 任务执行完成后,调用 afterExecute,这也可能会抛出异常,这也会导致线程死亡。
     *
     * The net effect of the exception mechanics is that afterExecute
     * and the thread's UncaughtExceptionHandler have as accurate
     * information as we can provide about any problems encountered by
     * user code.
     *
     * @param w the worker
     */
    final void runWorker(Worker w) {
        //获取当前线程
        Thread wt = Thread.currentThread();
        //获取第一个任务
        Runnable task = w.firstTask;
        w.firstTask = null;
        //解锁(允许中断)
        w.unlock(); // allow interrupts
        //最终退出使用
        boolean completedAbruptly = true;
        try {
            //循环从队列中获取一个线程
            while (task != null || (task = getTask()) != 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) ||
                     (Thread.interrupted() &&
                      runStateAtLeast(ctl.get(), STOP))) &&
                    !wt.isInterrupted())
                    wt.interrupt();
                try {
                    //执行task的方法
                    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;
                    //自动 并解锁
                    w.completedTasks++;
                    w.unlock();
                }
            }
            //全部执行完
            completedAbruptly = false;
        } finally {
            processWorkerExit(w, completedAbruptly);
        }
    }

    // Public constructors and methods

    //构造方法带参
    //corePoolSize 核心数
    //maximumPoolSize 最大线程数量
    //keepAliveTime 超时时间
    //TimeUnit 时间单位
    //BlockingQueue 执行队列任务
    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), defaultHandler);
    }

    //同上类似
    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             threadFactory, defaultHandler);
    }

    //同上类似
    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              RejectedExecutionHandler handler) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), handler);
    }


    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler) {
        if (corePoolSize < 0 ||
            maximumPoolSize <= 0 ||
            maximumPoolSize < corePoolSize ||
            keepAliveTime < 0)
            throw new IllegalArgumentException();
        if (workQueue == null || threadFactory == null || handler == null)
            throw new NullPointerException();
        this.acc = System.getSecurityManager() == null ?
                null :
                AccessController.getContext();
        this.corePoolSize = corePoolSize;
        this.maximumPoolSize = maximumPoolSize;
        this.workQueue = workQueue;
        this.keepAliveTime = unit.toNanos(keepAliveTime);
        this.threadFactory = threadFactory;
        this.handler = handler;
    }

    //提交执行任务(异步的)
    public void execute(Runnable command) {
        if (command == null)
            throw new NullPointerException();
        /*
         *
         *分 3 个步骤进行:
                1. 如果正在运行的线程少于 corePoolSize,尝试使用给定命令作为其第一个任务来启动新线程。
                对 addWorker 的调用以原子方式检查 runState 和 workerCount,通过返回 false 来防止错误警报,这些警报会在空闲添加线程。
                2. 如果一个任务可以成功排队,那么仍然需要仔细检查我们是否应该添加一个线程(因为现有线程自上次检查以来就死了)或者池在进入此方法后关闭了。
                重新检查状态,如有必要,如果停止,则回滚排队,如果没有,则启动一个新线程。
                3.如果不能排队任务,那么尝试添加一个新线程。如果失败了,要么是已经关闭或饱和,因此拒绝这项任务。
         Proceed in 3 steps:

        int c = ctl.get();
        if (workerCountOf(c) < corePoolSize) {
            if (addWorker(command, true))
                return;
            c = ctl.get();
        }
        if (isRunning(c) && workQueue.offer(command)) {
            int recheck = ctl.get();
            if (! isRunning(recheck) && remove(command))
                reject(command);
            else if (workerCountOf(recheck) == 0)
                addWorker(null, false);
        }
        else if (!addWorker(command, false))
            reject(command);
    }

    //关闭线程池(无返回)
    public void shutdown() {
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            checkShutdownAccess();
            advanceRunState(SHUTDOWN);
            interruptIdleWorkers();
            onShutdown(); // hook for ScheduledThreadPoolExecutor
        } finally {
            mainLock.unlock();
        }
        tryTerminate();
    }

    //关闭线程池(并返回等待执行的任务的列表。)
    public List<Runnable> shutdownNow() {
        List<Runnable> tasks;
        //逻辑是上锁然后获取列表,最后返回
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            checkShutdownAccess();
            advanceRunState(STOP);
            interruptWorkers();
            tasks = drainQueue();
        } finally {
            mainLock.unlock();
        }
        tryTerminate();
        return tasks;
    }
    //判断当前是否关闭 true是 false否
    public boolean isShutdown() {
        return ! isRunning(ctl.get());
    }

    //判断是否未完全停止(正在关机中)
    public boolean isTerminating() {
        int c = ctl.get();
        return ! isRunning(c) && runStateLessThan(c, TERMINATED);
    }
    //判断线程是否已终止
    public boolean isTerminated() {
        return runStateAtLeast(ctl.get(), TERMINATED);
    }
    //带超时时间终止方法
    public boolean awaitTermination(long timeout, TimeUnit unit)
        throws InterruptedException {
        long nanos = unit.toNanos(timeout);
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            for (;;) {
                if (runStateAtLeast(ctl.get(), TERMINATED))
                    return true;
                if (nanos <= 0)
                    return false;
                nanos = termination.awaitNanos(nanos);
            }
        } finally {
            mainLock.unlock();
        }
    }

    //关闭方法
    protected void finalize() {
        SecurityManager sm = System.getSecurityManager();
        if (sm == null || acc == null) {
            shutdown();
        } else {
            PrivilegedAction<Void> pa = () -> { shutdown(); return null; };
            AccessController.doPrivileged(pa, acc);
        }
    }

    //设置用于创建新线程的线程工厂。
    public void setThreadFactory(ThreadFactory threadFactory) {
        if (threadFactory == null)
            throw new NullPointerException();
        this.threadFactory = threadFactory;
    }

   //获取线程工厂
    public ThreadFactory getThreadFactory() {
        return threadFactory;
    }

    //为不可执行的任务设置新的处理程序。
    public void setRejectedExecutionHandler(RejectedExecutionHandler handler) {
        if (handler == null)
            throw new NullPointerException();
        this.handler = handler;
    }

    /**
     * 返回不可执行任务的当前处理程序。
     *
     * @return the current handler
     * @see #setRejectedExecutionHandler(RejectedExecutionHandler)
     */
    public RejectedExecutionHandler getRejectedExecutionHandler() {
        return handler;
    }

    /**
     * 设置线程的核心数。
     *
     * @param corePoolSize the new core size
     * @throws IllegalArgumentException if {@code corePoolSize < 0}
     * @see #getCorePoolSize
     */
    public void setCorePoolSize(int corePoolSize) {
        if (corePoolSize < 0)
            throw new IllegalArgumentException();
        int delta = corePoolSize - this.corePoolSize;
        this.corePoolSize = corePoolSize;
        if (workerCountOf(ctl.get()) > corePoolSize)
            interruptIdleWorkers();
        else if (delta > 0) {
            // We don't really know how many new threads are "needed".
            // As a heuristic, prestart enough new workers (up to new
            // core size) to handle the current number of tasks in
            // queue, but stop if queue becomes empty while doing so.
            int k = Math.min(delta, workQueue.size());
            while (k-- > 0 && addWorker(null, true)) {
                if (workQueue.isEmpty())
                    break;
            }
        }
    }

    /**
     * Returns the core number of threads.
     *
     * @return the core number of threads
     * @see #setCorePoolSize
     */
    public int getCorePoolSize() {
        return corePoolSize;
    }

    /**
     *启动核心线程,使其空闲等待工作。
     *
     * @return {@code true} if a thread was started
     */
    public boolean prestartCoreThread() {
        return workerCountOf(ctl.get()) < corePoolSize &&
            addWorker(null, true);
    }

    /**
     * Same as prestartCoreThread except arranges that at least one
     * thread is started even if corePoolSize is 0.
     */
    void ensurePrestart() {
        int wc = workerCountOf(ctl.get());
        if (wc < corePoolSize)
            addWorker(null, true);
        else if (wc == 0)
            addWorker(null, false);
    }

    /**
     * 启动所有核心线程
     *
     * @return the number of threads started
     */
    public int prestartAllCoreThreads() {
        int n = 0;
        while (addWorker(null, true))
            ++n;
        return n;
    }

    /**
     * 如果此线程池允许核心线程超时,则返回 true。
       如果 keepAlive 时间内没有任务到达,则返回 true
       如果需要,在新任务到达时替换。
     *
     * @return {@code true} if core threads are allowed to time out,
     * else {@code false}
     *
     * @since 1.6
     */
    public boolean allowsCoreThreadTimeOut() {
        return allowCoreThreadTimeOut;
    }

    //同上类似
    public void allowCoreThreadTimeOut(boolean value) {
        if (value && keepAliveTime <= 0)
            throw new IllegalArgumentException("Core threads must have nonzero keep alive times");
        if (value != allowCoreThreadTimeOut) {
            allowCoreThreadTimeOut = value;
            if (value)
                interruptIdleWorkers();
        }
    }

    //设置最大的线程核心数
    public void setMaximumPoolSize(int maximumPoolSize) {
        if (maximumPoolSize <= 0 || maximumPoolSize < corePoolSize)
            throw new IllegalArgumentException();
        this.maximumPoolSize = maximumPoolSize;
        if (workerCountOf(ctl.get()) > maximumPoolSize)
            interruptIdleWorkers();
    }

    /**
     * Returns the maximum allowed number of threads.
     *
     * @return the maximum allowed number of threads
     * @see #setMaximumPoolSize
     */
    public int getMaximumPoolSize() {
        return maximumPoolSize;
    }

    //设置线程空闲超时时间
    public void setKeepAliveTime(long time, TimeUnit unit) {
        if (time < 0)
            throw new IllegalArgumentException();
        if (time == 0 && allowsCoreThreadTimeOut())
            throw new IllegalArgumentException("Core threads must have nonzero keep alive times");
        long keepAliveTime = unit.toNanos(time);
        long delta = keepAliveTime - this.keepAliveTime;
        this.keepAliveTime = keepAliveTime;
        if (delta < 0)
            interruptIdleWorkers();
    }

    //获取空间时间(这个单位有点坑,没用到 )
    public long getKeepAliveTime(TimeUnit unit) {
        return unit.convert(keepAliveTime, TimeUnit.NANOSECONDS);
    }

    /* User-level queue utilities */

    //返回执行任务队列
    public BlockingQueue<Runnable> getQueue() {
        return workQueue;
    }

    //删除任务方法
    public boolean remove(Runnable task) {
        boolean removed = workQueue.remove(task);
        tryTerminate(); // In case SHUTDOWN and now empty
        return removed;
    }

    //尝试从工作队列中删除所有已取消任务
    public void purge() {
        final BlockingQueue<Runnable> q = workQueue;
        try {
            Iterator<Runnable> it = q.iterator();
            //遍历查找
            while (it.hasNext()) {
                Runnable r = it.next();
                if (r instanceof Future<?> && ((Future<?>)r).isCancelled())
                    it.remove();
            }
        } catch (ConcurrentModificationException fallThrough) {
            // Take slow path if we encounter interference during traversal.
            // Make copy for traversal and call remove for cancelled entries.
            // The slow path is more likely to be O(N*N).
            for (Object r : q.toArray())
                if (r instanceof Future<?> && ((Future<?>)r).isCancelled())
                    q.remove(r);
        }

        tryTerminate(); // In case SHUTDOWN and now empty
    }

    /* Statistics */

    //返回池中的当前线程数。
    public int getPoolSize() {
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            // Remove rare and surprising possibility of
            // isTerminated() && getPoolSize() > 0
            return runStateAtLeast(ctl.get(), TIDYING) ? 0
                : workers.size();
        } finally {
            mainLock.unlock();
        }
    }

    //返回存活线程数
    public int getActiveCount() {
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            int n = 0;
            for (Worker w : workers)
                if (w.isLocked())
                    ++n;
            return n;
        } finally {
            mainLock.unlock();
        }
    }

   //返回最大线程数
    public int getLargestPoolSize() {
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            return largestPoolSize;
        } finally {
            mainLock.unlock();
        }
    }

    //返回当前任务数
    public long getTaskCount() {
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            long n = completedTaskCount;
            for (Worker w : workers) {
                n += w.completedTasks;
                if (w.isLocked())
                    ++n;
            }
            return n + workQueue.size();
        } finally {
            mainLock.unlock();
        }
    }

    //返回已完成执行的任务的大致总数。
    public long getCompletedTaskCount() {
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            long n = completedTaskCount;
            for (Worker w : workers)
                n += w.completedTasks;
            return n;
        } finally {
            mainLock.unlock();
        }
    }


    public String toString() {
        long ncompleted;
        int nworkers, nactive;
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            ncompleted = completedTaskCount;
            nactive = 0;
            nworkers = workers.size();
            for (Worker w : workers) {
                ncompleted += w.completedTasks;
                if (w.isLocked())
                    ++nactive;
            }
        } finally {
            mainLock.unlock();
        }
        int c = ctl.get();
        String rs = (runStateLessThan(c, SHUTDOWN) ? "Running" :
                     (runStateAtLeast(c, TERMINATED) ? "Terminated" :
                      "Shutting down"));
        return super.toString() +
            "[" + rs +
            ", pool size = " + nworkers +
            ", active threads = " + nactive +
            ", queued tasks = " + workQueue.size() +
            ", completed tasks = " + ncompleted +
            "]";
    }

    /* Extension hooks */

    /**
     * Method invoked prior to executing the given Runnable in the
     * given thread. This method is invoked by thread {@code t} that
     * will execute task {@code r}, and may be used to re-initialize
     * ThreadLocals, or to perform logging.
     *
     * <p>This implementation does nothing, but may be customized in
     * subclasses. Note: To properly nest multiple overridings, subclasses
     * should generally invoke {@code super.beforeExecute} at the end of
     * this method.
     *
     * @param t the thread that will run task {@code r}
     * @param r the task that will be executed
     */
    protected void beforeExecute(Thread t, Runnable r) { }

    /**
     * Method invoked upon completion of execution of the given Runnable.
     * This method is invoked by the thread that executed the task. If
     * non-null, the Throwable is the uncaught {@code RuntimeException}
     * or {@code Error} that caused execution to terminate abruptly.
     *
     * <p>This implementation does nothing, but may be customized in
     * subclasses. Note: To properly nest multiple overridings, subclasses
     * should generally invoke {@code super.afterExecute} at the
     * beginning of this method.
     *
     * <p><b>Note:</b> When actions are enclosed in tasks (such as
     * {@link FutureTask}) either explicitly or via methods such as
     * {@code submit}, these task objects catch and maintain
     * computational exceptions, and so they do not cause abrupt
     * termination, and the internal exceptions are <em>not</em>
     * passed to this method. If you would like to trap both kinds of
     * failures in this method, you can further probe for such cases,
     * as in this sample subclass that prints either the direct cause
     * or the underlying exception if a task has been aborted:
     *
     * <pre> {@code
     * class ExtendedExecutor extends ThreadPoolExecutor {
     * // ...
     * protected void afterExecute(Runnable r, Throwable t) {
     * super.afterExecute(r, t);
     * if (t == null && r instanceof Future<?>) {
     * try {
     * Object result = ((Future<?>) r).get();
     * } catch (CancellationException ce) {
     * t = ce;
     * } catch (ExecutionException ee) {
     * t = ee.getCause();
     * } catch (InterruptedException ie) {
     * Thread.currentThread().interrupt(); // ignore/reset
     * }
     * }
     * if (t != null)
     * System.out.println(t);
     * }
     * }}</pre>
     *
     * @param r the runnable that has completed
     * @param t the exception that caused termination, or null if
     * execution completed normally
     */
    protected void afterExecute(Runnable r, Throwable t) { }

    /**
     * Method invoked when the Executor has terminated. Default
     * implementation does nothing. Note: To properly nest multiple
     * overridings, subclasses should generally invoke
     * {@code super.terminated} within this method.
     */
    protected void terminated() { }

    /* Predefined RejectedExecutionHandlers */

    /**
     * A handler for rejected tasks that runs the rejected task
     * directly in the calling thread of the {@code execute} method,
     * unless the executor has been shut down, in which case the task
     * is discarded.
     */
    public static class CallerRunsPolicy implements RejectedExecutionHandler {
        /**
         * Creates a {@code CallerRunsPolicy}.
         */
        public CallerRunsPolicy() { }

        /**
         * Executes task r in the caller's thread, unless the executor
         * has been shut down, in which case the task is discarded.
         *
         * @param r the runnable task requested to be executed
         * @param e the executor attempting to execute this task
         */
        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            if (!e.isShutdown()) {
                r.run();
            }
        }
    }

    /**
     * 拒绝任务的处理程序,该处理程序引发
     * {@code RejectedExecutionException}.
     */
    public static class AbortPolicy implements RejectedExecutionHandler {
        /**
         * Creates an {@code AbortPolicy}.
         */
        public AbortPolicy() { }

        /**
         * Always throws RejectedExecutionException.
         *
         * @param r the runnable task requested to be executed
         * @param e the executor attempting to execute this task
         * @throws RejectedExecutionException always
         */
        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            throw new RejectedExecutionException("Task " + r.toString() +
                                                 " rejected from " +
                                                 e.toString());
        }
    }

    /**
     * 以静默方式丢弃被拒绝的任务的处理程序。
     */
    public static class DiscardPolicy implements RejectedExecutionHandler {
        /**
         * Creates a {@code DiscardPolicy}.
         */
        public DiscardPolicy() { }

        /**
         * Does nothing, which has the effect of discarding task r.
         *
         * @param r the runnable task requested to be executed
         * @param e the executor attempting to execute this task
         */
        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
        }
    }

    /**
     * 被拒绝任务的处理程序,它丢弃最早的未处理请求,
     */
    public static class DiscardOldestPolicy implements RejectedExecutionHandler {
        /**
         * Creates a {@code DiscardOldestPolicy} for the given executor.
         */
        public DiscardOldestPolicy() { }

        /**
         * Obtains and ignores the next task that the executor
         * would otherwise execute, if one is immediately available,
         * and then retries execution of task r, unless the executor
         * is shut down, in which case task r is instead discarded.
         *
         * @param r the runnable task requested to be executed
         * @param e the executor attempting to execute this task
         */
        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            if (!e.isShutdown()) {
                e.getQueue().poll();
                e.execute(r);
            }
        }
    }
}

Principio del grupo de subprocesos

fd4f796f7d1151c83a24799d60cee4b9.png

Proceso de implementación:

  • Cuando la cantidad de tareas de ejecución es menor que la cantidad de subprocesos principales (corePoolSize), se crea un nuevo subproceso para su ejecución.

  • Cuando el número de tareas de ejecución >= el número de subprocesos principales (corePoolSize) y la cola de bloqueo en el grupo de subprocesos no está llena, agregue la tarea a la cola de bloqueo;

  • Cuando la cantidad de tareas a ejecutar >= la cantidad de subprocesos principales (corePoolSize) y cuando la cantidad de tareas a ejecutar < la cantidad máxima de subprocesos en el grupo de subprocesos, la secuencia de bloqueo en el grupo de subprocesos está llena y se crea un nuevo hilo para su ejecución;

  • Cuando la cantidad de tareas a ejecutar >= la cantidad de subprocesos principales (corePoolSize) y la secuencia de bloqueo en el grupo de subprocesos está llena, la tarea se procesará de acuerdo con la estrategia de rechazo y el método de procesamiento predeterminado es lanzar directamente una excepción.

El proceso de ejecución de ejecutar:

b2766ba115f1424c2f16447efd9495f9.png

por fin

    Si hay muchos subprocesos en el sistema, se recomienda usar el grupo de subprocesos para evitar algunos factores de inestabilidad en el sistema causados ​​por subprocesos nuevos manualmente. En particular, el grupo de subprocesos se puede usar para administrar y garantizar la estabilidad del Sistema Por supuesto, cómo ajustarlo se recomienda consultar el "Manual de desarrollo de Alibaba".

Este artículo solo escribe parte del código fuente de ThreadPoolExecutor sin escribir comentarios en profundidad. Los estudiantes que necesiten más detalles pueden profundizar o comunicarse en privado.

referencias

    https://zhuanlan.zhihu.com/p/505594640

Supongo que te gusta

Origin blog.csdn.net/qq_16498553/article/details/129543660
Recomendado
Clasificación