Hay cuatro tipos de grupos de subprocesos que vienen con Java

¿Qué cuatro tipos de grupos de subprocesos están predefinidos por Java?

  • newSingleThreadExecutor: grupo de subprocesos con número de subproceso único (número de subproceso principal = número máximo de subprocesos = 1)
  • newFixedThreadPool: un grupo de subprocesos con un número fijo de subprocesos (subprocesos principales = subprocesos máximos = personalizado)
  • newCacheThreadPool: grupo de subprocesos almacenables en caché (subprocesos principales = 0, subprocesos máximos = Integer.MAX_VALUE)
  • newScheduledThreadPool: grupo de subprocesos que admite tareas programadas o periódicas (subprocesos principales = personalizado, subprocesos máximos = Integer.MAX_VALUE)

¿Cuál es la diferencia entre los cuatro grupos de subprocesos?

Las cuatro clases de grupo de subprocesos anteriores heredan ThreadPoolExecutor y devuelven un nuevo ThreadPoolExecutor (parámetro) directamente cuando se crean. La diferencia entre ellas es que los parámetros en el ThreadPoolExecutor definido (parámetro) son diferentes, y ThreadPoolExecutor hereda la clase de interfaz ExecutorService.

  • nuevoGrupo de subprocesos fijos
定义:
ExecutorService executorService=Executors.newFixedThreadPool(2);

Desventajas: se utiliza la cola de bloqueo de lista enlazada de LinkBlockQueue.Cuando la velocidad de acumulación de tareas es mayor que la velocidad de procesamiento, es fácil acumular tareas y causar un desbordamiento de memoria OOM

  • nuevoSingleThreadExecutor
定义:ExecutorService executorService =Executors.newSingleThreadExecutor();

El código anterior es similar al nuevo FixedThreadPoop(1), pero es diferente, porque hay una capa de FinalizableDelegatedExecutorService fuera, su función:

Se puede ver que la esencia de fixedExecutorService es ThreadPoolExecutor, por lo que se puede obligar a fixedExecutorService a convertirse en ThreadPoolExecutor, pero singleExecutorService no tiene nada que ver con ThreadPoolExecutor, por lo que la transferencia forzada falla, por lo que después de crear newSingleThreadExecutor(), sus parámetros de grupo de subprocesos no se puede modificar, y es realmente un solo subproceso.

Desventajas: se utiliza la cola de bloqueo de lista enlazada de LinkBlockQueue.Cuando la velocidad de acumulación de tareas es mayor que la velocidad de procesamiento, es fácil acumular tareas y causar un desbordamiento de memoria OOM

  • newCacheThreadPool
定义:ExecutorService executorService=Executors.newCacheThreadPool();

Desventajas: SynchronousQueue es una implementación de BlockingQueue, también es una cola, porque la cantidad máxima de subprocesos es Integer.MAX_VALUE, por lo que cuando hay demasiados subprocesos, es fácil que se desborde la memoria OOM.

  • Agrupación de subprocesos programados
定义:ExecutorService executorService=Executors.newScheduledThreadPool(2);
Código fuente: 
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) { 
        //ScheduledThreadPoolExecutor hereda ThreadPoolExecutor 
        return new ScheduledThreadPoolExecutor(corePoolSize); 
    } 
    
public ScheduledThreadPoolExecutor(int corePoolSize) { 
    //ScheduledThreadPoolExecutor hereda ThreadPoolExecutor, por lo que super() llamará al constructor de ThreadPoolExecutor para inicializar y devuelva A 
    ThreadPoolExecutor , y ThreadPoolExecutor realiza la implementación de la interfaz ExecutorService 
    // el ScheduledThreadPoolExecutor final también devuelve la clase de implementación de la interfaz ExecutorService como los grupos de subprocesos anteriores 
          . )); 
}

¿Cuáles son los parámetros importantes del grupo de subprocesos?

El método de construcción de ThreadPoolExecutor es el siguiente:

  • keepAliveTime se refiere a cuánto tiempo estos subprocesos no centrales cuyo número de subproceso actual está entre [número de subproceso principal, número máximo de subprocesos] esperan el tiempo de inactividad y salen del grupo de subprocesos cuando no hay trabajo;
  • El tamaño de la columna de espera no tiene nada que ver con el número máximo de subprocesos Prioridad de creación de subprocesos = subproceso principal > cola de bloqueo > subproceso expandido (los subprocesos solo se pueden expandir cuando el número actual de subprocesos principales es menor que el número máximo de subprocesos )
  • Si la cantidad de subprocesos principales es 5, la longitud de la cola de espera es 3 y la cantidad máxima de subprocesos es 10: cuando la cantidad de subprocesos continúa aumentando, se crean 5 subprocesos principales primero y cuando la cantidad de subprocesos principales está llena , los subprocesos se lanzan a la cola de espera y la cola de espera está llena (3 subprocesos), la cantidad máxima de subprocesos se comparará en este momento (solo puede aparecer después de esperar a que se elimine la cantidad máxima de subprocesos), y puede continuar creando 2 subprocesos (5+3+2), si el número de subprocesos supera el número máximo de subprocesos, se ejecuta la política de rechazo;
  • Si la cantidad de subprocesos principales es 5, la longitud de la cola de espera es 3 y la cantidad máxima de subprocesos es 7: cuando la cantidad de subprocesos aumenta, primero se crean 5 subprocesos principales y cuando la cantidad de subprocesos principales es lleno, los subprocesos se arrojan a la cola de espera. Cuando hay 2 subprocesos, se alcanza el número máximo de subprocesos (5+2=7), pero la columna de espera no está llena, así que no se preocupe por el número máximo de subprocesos. subprocesos hasta que la columna de espera esté llena (3 subprocesos bloqueados), en cuyo momento será el más grande El número de subprocesos (solo se puede mostrar el número máximo de subprocesos cuando la columna de espera está llena), en este momento, el núcleo + esperando a que se elimine la columna = 5 + 3 = 8 > 7 = el número máximo de subprocesos, es decir, se ha alcanzado el número máximo de subprocesos y se ejecuta la política de rechazo;
  • Si configura la columna de espera para que se elimine como columna de eliminación ilimitada de LinkedBlockingQueue, la columna eliminada es infinita y nunca llegará al paso de juzgar la cantidad máxima de subprocesos.

Cómo personalizar el grupo de subprocesos

Los grupos de subprocesos se pueden personalizar utilizando colas limitadas, fábricas de creación de subprocesos personalizadas, ThreadFactory y controladores de políticas de rechazo.

ThreadTest de clase pública { 
    public static void main(String[] args) throws InterruptedException, IOException { 
        int corePoolSize = 2; 
        int tamaño máximo de grupo = 4; 
        long keepAliveTime = 10; 
        unidad de unidad de tiempo = unidad de tiempo.SEGUNDOS; 
        BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(2); 
        ThreadFactory threadFactory = new NameTreadFactory(); 
        Manejador RejectedExecutionHandler = new MyIgnorePolicy(); 
       ThreadPoolExecutor ejecutor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, unit, 
                workQueue, threadFactory, handler); 
        ejecutor.prestartAllCoreThreads(); // 预启动所有核心线程        
        para (int i = 1; i <= 10; i++) { 
            MiTarea tarea = new MiTarea(String.valueOf(i)); 
            ejecutor.ejecutar(tarea); 
        } 
        Sistema.en.lectura(); //阻塞主线程
    } 
    clase estática NameTreadFactory implementa ThreadFactory { 
        private final AtomicInteger mThreadNum = new AtomicInteger(1); 
        @Override 
        public Thread newThread(Runnable r) { 
            Thread t = new Thread(r, "my-thread-" + mThreadNum.getAndIncrement()); 
            System.out.println(t.getName() + " ha sido creado"); 
            devolver t; 
        } 
    } 

    clase estática pública MyIgnorePolicy implementa RejectedExecutionHandler {
        @Override  
        public void disabledExecution(Runnable r, ThreadPoolExecutor e) {
            doLog(r, e); 
        } 
        private void doLog(Runnable r, ThreadPoolExecutor e) { 
            // 可做日志记录等
            System.err.println( r.toString() + "rechazado"); 
// System.out.println("completedTaskCount: " + e.getCompletedTaskCount()); 
        } 
    } 

    La clase estática MyTask implementa Runnable { 
        private String name; 
        public MyTask(String nombre) { 
            this.name = nombre; 
        } 
        @Override 
        public void run() { 
            try { 
                System.out.println(this.toString() + " se está ejecutando!");
                Thread.sleep(3000); //Hacer que la tarea se ejecute más lentamente 
            } catch (InterruptedException e) {
                e.printStackTrace(); 
            } 
        } 
        public String getName() { 
            return nombre; 
        } 
        @Override 
        public String toString() { 
            return "MyTask [name=" + name + "]"; 
        } 
    } 
}

resultado de la operación:

Entre ellos, los subprocesos 7-10 son rechazados por la política de rechazo. Después de ejecutar los subprocesos 1 y 2, los subprocesos 3 y 6 ingresan al grupo de subprocesos principales para su ejecución. En este momento, los subprocesos 4 y 5 están esperando en la cola de tareas para su ejecución. , y se ejecutan los subprocesos 3 y 6. Después de terminar, notifique a los subprocesos 4 y 5 para que se ejecuten

Supongo que te gusta

Origin blog.csdn.net/Trouvailless/article/details/124427132
Recomendado
Clasificación