Java multithreading 10: grupo de subprocesos personalizado ThreadPoolExecutor

Introducción: hay un párrafo como este en la nueva versión del manual de desarrollo 619java de Alibaba

1. [Obligatorio] Al crear un hilo o grupo de hilos, especifique un nombre de hilo significativo para facilitar el rastreo en caso de errores.
2. [Obligatorio] Los recursos de subprocesos deben proporcionarse a través del grupo de subprocesos y no se permite crear subprocesos explícitamente en la aplicación.
Nota: La ventaja del grupo de subprocesos es reducir el tiempo empleado en crear y destruir subprocesos y la sobrecarga de los recursos del sistema, y ​​resolver el problema de la insuficiencia de recursos
. Si no se utiliza el grupo de subprocesos, puede hacer que el sistema cree una gran cantidad de subprocesos del mismo tipo y provocar el problema de quedarse sin memoria o "cambiar en exceso".
3. [Obligatorio] No se permite crear grupos de subprocesos usando Ejecutores, pero se crean a través de ThreadPoolExecutor Esta
forma de procesamiento permite a los estudiantes escribir más claramente las reglas de funcionamiento del grupo de subprocesos y evitar el riesgo de agotamiento de recursos.

Nota: Los inconvenientes de los objetos del grupo de subprocesos devueltos por los ejecutores son los siguientes: 1) FixedThreadPool y SingleThreadPool: la
longitud de la cola de solicitudes permitida es Integer.MAX_VALUE, que puede acumular una gran cantidad de solicitudes, lo que lleva a OOM. 2) CachedThreadPool: La
cantidad permitida de subprocesos que se crearán es Integer.MAX_VALUE, que puede crear una gran cantidad de subprocesos, lo que da como resultado OOM.

 Beneficios del grupo de subprocesos personalizados

1. Reutilice subprocesos en el grupo de subprocesos para evitar el consumo de rendimiento causado por la creación y destrucción frecuentes de subprocesos.

2. Control más eficaz del número máximo de subprocesos simultáneos para evitar la congestión del sistema causada por la apropiación excesiva de recursos por parte de los subprocesos.

3. Gestione los hilos de forma eficaz.

Dado que hay tantos beneficios, expliquemos el grupo de subprocesos personalizado ThreadPoolExecutor.

ExecutorService exec = new ThreadPoolExecutor(20,
                            100,
                            60,
                            TimeUnit.SECONDS,
                            new ArrayBlockingQueue<Runnable>(4),
                            Executors.defaultThreadFactory(),
                            new ThreadPoolExecutor.CallerRunsPolicy());

1. Explicación detallada de los parámetros

7 parámetros de arriba a abajo

1.corePoolSize

El número de subprocesos centrales. Una vez que se crea el grupo de subprocesos, no hay subprocesos en el grupo de subprocesos de forma predeterminada. En su lugar, se crean subprocesos para realizar tareas después de esperar la llegada de las tareas. Cuando el número de subprocesos en el grupo de subprocesos alcanza corePoolSize, las nuevas tareas agregarse a En la cola de caché, es decir, workQueue , a menos que se llame al método ThreadPoolExecutor # prestartAllCoreThreads () o al método ThreadPoolExecutor # prestartCoreThread () (a partir de los nombres de estos dos métodos, se puede ver que significa pre subprocesos creados, es decir, antes de que no llegue ninguna tarea Simplemente cree subprocesos corePoolSize o un subproceso).

PD: Muchas personas no saben cuánto se debe completar este número. De hecho, no tienen que estar particularmente enredados. Solo complételo de acuerdo con la situación real. Si no lo sabe, simplemente tome el siguientes valores de acuerdo con la escritura de los ingenieros de Ali:
int NUMBER_OF_CORES = Runtime.getRuntime () .availableProcessors ();

2.tamaño máximo de la piscina

El número máximo de subprocesos en el grupo de subprocesos. Indica el número máximo de subprocesos que se pueden crear en el grupo de subprocesos. Mucha gente piensa que su función es así: "Cuando el número de tareas en el grupo de subprocesos excede corePoolSize, el grupo de subprocesos continuará creando subprocesos hasta que el número de subprocesos en el grupo de subprocesos es menor que el maximumPoolSize "De hecho, esta comprensión es completamente incorrecta. Su función real es: cuando el número de subprocesos en el grupo de subprocesos es igual a corePoolSize y workQueue lleno, entonces deberíamos ver cuándo si el número de subprocesos es mayor que antes de maximumPoolSize , si es menor que el valor definido, maximumPoolSize, continuará creando un hilo para realizar la tarea; de lo contrario, las llamadas a la tarea correspondiente niegan la política para rechazar esta tarea . Además, los subprocesos que superan corePoolSize se denominan "subproceso inactivo". Esta parte del subproceso tendrá un tiempo de supervivencia inactivo máximo (keepAliveTime). Si no se asigna ninguna tarea después de este tiempo de supervivencia inactivo, esta parte del subproceso se reciclará.

3.keepAliveTime

Controla el tiempo de supervivencia inactivo del hilo "inactivo" . Este subproceso inactivo es el subproceso recién creado después de corePoolSize mencionado anteriormente. De forma predeterminada, este parámetro solo se iniciará cuando el número de subprocesos en el grupo de subprocesos sea mayor que corePoolSize y estos "subprocesos inactivos" no se asignan tareas. Además, si se llama al método ThreadPoolExecutor # allowCoreThreadTimeOut (boolean), el número de subprocesos en el grupo de subprocesos no es mayor que corePoolSize, y estos subprocesos principales no tienen tareas asignadas, el parámetro keepAliveTime también funcionará.

4.unidad

La unidad de tiempo del parámetro keepAliveTime tiene 7 valores, que se definen en TimeUtil:

TimeUnit.DAYS;              //天
TimeUnit.HOURS;             //小时
TimeUnit.MINUTES;           //分钟
TimeUnit.SECONDS;           //秒
TimeUnit.MILLISECONDS;      //毫秒
TimeUnit.MICROSECONDS;      //微妙
TimeUnit.NANOSECONDS;       //纳秒

5.workQueue

Bloqueando la cola. Si el número de subprocesos en el grupo de subprocesos actual> = corePoolSize, cada vez que llega una tarea, intentará agregarla a la cola. Tenga en cuenta que mientras corePoolSize exceda el corePoolSize, la tarea se agregará a la cola de caché . La adición puede tener éxito o no. Si tiene éxito, esperará a que el subproceso inactivo ejecute la tarea. Si la adición falla (generalmente la cola está llena), decidirá cómo manejar la tarea de acuerdo con el subproceso actual. estado del grupo (si el número de subprocesos es <maximumPoolSize, entonces cree un nuevo subproceso; si el subproceso es Si el número> = maximumPoolSize, se realizará un procesamiento específico de acuerdo con la estrategia de rechazo).

Las colas de bloqueo más utilizadas son:

1)ArrayBlockingQueue       //基于数组的先进先出队列,此队列创建时必须指定大小;
2)LinkedBlockingQueue      //基于链表的先进先出队列,如果创建时没有指定此队列大小,则默认为Integer.MAX_VALUE;
3)synchronousQueue        //这个队列比较特殊,它不会保存提交的任务,而是将直接新建一个线程来执行新来的任务。

6.threadFactory

Fábrica de hilos. Se utiliza para crear subprocesos para el grupo de subprocesos.Cuando no especificamos la fábrica de subprocesos, el grupo de subprocesos llamará para Executors.defaultThreadFactory()crear la fábrica de subprocesos predeterminada, y las prioridades de subprocesos para la creación posterior son todas Thread.NORM_PRIORITY. Si especificamos la fábrica de subprocesos, podemos realizar ciertas operaciones en los subprocesos generados.

7.manipulador

Negarse a hacer cumplir la política. Cuando la cola de caché del grupo de subprocesos está llena y el número de subprocesos en el grupo de subprocesos alcanza el tamaño máximo de la agrupación, si hay tareas por venir, se adoptará la estrategia de rechazo de tareas. Por lo general, existen las siguientes cuatro estrategias:

ThreadPoolExecutor.AbortPolicy:         // 丢弃任务并抛出RejectedExecutionException异常。
ThreadPoolExecutor.DiscardPolicy:       // 也是丢弃任务,但是不抛出异常。
ThreadPoolExecutor.DiscardOldestPolicy:    // 丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程)
ThreadPoolExecutor.CallerRunsPolicy:      // 由调用线程处理该任务

Los 4 tipos predeterminados no son muy amigables, además de la política de rechazo anterior, también podemos personalizar la política de rechazo

 ExecutorService pool = new ThreadPoolExecutor(// 自定义一个线程池

                1, // coreSize

                2, // maxSize

                60, // 60s

                TimeUnit.SECONDS, new ArrayBlockingQueue<>(3) // 有界队列,容量是3个

                , Executors.defaultThreadFactory()

                , new MyRejected()//自定义拒绝策略

        );

La clase personalizada MyRejectedl hereda RejectedExecutionHandler 

public class MyRejected implements RejectedExecutionHandler {

 

    @Override

    public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {

        MyTask task = (MyTask) r;

        System.out.println("报警信息:"+task.getTaskName()+" 被线程池拒绝,没有被执行");

        //可以往消息队列中间件里面放 可以发Email等等

    }

}

 

Two. ThreadPoolExecutor's tres formas de enviar tareas

ejecutorService.execute (Runnable); // Sin valor de retorno
ejecutorService.submit (Ejecutable); // Devuelve el valor
inVokeAny (); Devuelve un resultado aleatorio, invokeAll (); // Devuelve todos los resultados

Para obtener más información, consulte: https://www.cnblogs.com/ldq2016/p/8072563.html


3. Cierre del grupo de subprocesos

Cuando no necesitamos usar el grupo de subprocesos, necesitamos cerrarlo ... Hay dos formas de cerrar el grupo de subprocesos ...

i.shutdown () ...

  Shutdown no cierra directamente el grupo de subprocesos, pero ya no acepta nuevas tareas ... Si hay tareas en el grupo de subprocesos, luego de que se ejecutan estas tareas, el grupo de subprocesos se cierra ...

ii.shutdownNow ()

  Este método significa que no se aceptarán nuevas tareas y las tareas en la cola de tareas se eliminarán directamente. Si hay algo en ejecución, intente detener ...

 

 

Supongo que te gusta

Origin blog.csdn.net/zhaofuqiangmycomm/article/details/113311879
Recomendado
Clasificación