Comenzando en Java 5, Java proporciona su propio grupo de hilos. Un grupo de subprocesos es un contenedor de subprocesos, que solo ejecuta un número nominal de hilos a la vez. java.util.concurrent.threadpoolexecutor es un grupo de hilos. Es muy flexible, pero también es complicado de usar, por lo que este artículo lo presentará.
Primero está el constructor. Tome el constructor más simple como ejemplo:
Public ThreadPoolExecutor (int corepoolSize, int MaximoMuproolSize, Long KeepAlivetime, TimeUnit Unit, Bloquingqueue <Runnable> WorkQuqueue)
Parece bastante complicado. Déjame presentarlo aquí.
CorePoolSize se refiere al tamaño de la piscina de hilo reservado.
MaximuMuboolSize se refiere al tamaño máximo de la piscina de rosca.
KeepAlivetime se refiere al tiempo de tiempo de espera cuando termina el hilo inactivo.
La unidad es una enumeración que representa la unidad de KeepAlivetime.
WorkQueue representa la cola para almacenar tareas.
Podemos entender la importancia de estos parámetros del proceso de trabajo del grupo de subprocesos. El proceso de trabajo del grupo de subprocesos es el siguiente:
1. Cuando se creó la piscina de hilo por primera vez, no había hilo adentro. La cola de tareas se pasa como parámetro. Sin embargo, incluso si hay tareas en la cola, el grupo de subprocesos no las ejecutará de inmediato.
2. Al llamar al método Execute () para agregar una tarea, el grupo de subprocesos hará el siguiente juicio:
A.
b.
C.
D.
3. Cuando un hilo completa una tarea, tomará una tarea de la cola para ejecutar.
4. Cuando un hilo no tiene nada que hacer, y lleva una cierta cantidad de tiempo (KeepAlivetime), el grupo de hilos juzgará que si el número de hilos que se ejecuta actualmente es mayor que CorePoolSize, entonces el hilo se detendrá. Entonces, después de que se completen todas las tareas del grupo de subprocesos, eventualmente se reducirá al tamaño de CorePoolSize.
Este proceso muestra que no es necesario ejecutar la tarea primero si se une a la tarea primero. Suponiendo que el tamaño de la cola es 10, CorePoolSize es 3 y MaximoMuboolSize es 6, luego, cuando se agregan 20 tareas, la orden de ejecución es la siguiente: Primero, las tareas 1, 2, 3 se ejecutan y luego se colocan las tareas 4 ~ 13 en la cola. En este momento, la cola está completa, las tareas 14, 15, 16 se ejecutarán de inmediato y las tareas 17 ~ 20 lanzarán excepciones. El orden final es: 1, 2, 3, 14, 15, 16, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13. Aquí hay un ejemplo de uso de la piscina de hilos:
Public static void main (string [] args) {Bloodqueue <runnable> queue = new LinkedBlockingqueue <Runnable> (); 0; out println (string.format ("hilo %d terminado", this.hashcode ()));
Una explicación de este ejemplo es la siguiente:
1. Bloqueque es solo una interfaz. La ventaja de usar LinkedBlokingqueue es que no hay límite de tamaño. De esta manera, debido a que la cola no estará llena, ejecutar () no lanzará una excepción, y el número de hilos que se ejecutan en el grupo de subprocesos nunca excederá CorePoolSize, por lo que el parámetro KeepAlivetime no tiene sentido.
2. El método apagado () no bloqueará. Después de llamar al método apagado (), el hilo principal termina inmediatamente, y el grupo de subprocesos continuará ejecutándose hasta que todas las tareas se ejecuten antes de detenerse. Si no se llama al método de cierre (), el grupo de subprocesos permanecerá para que se puedan agregar nuevas tareas en cualquier momento.
En este punto, solo he introducido una pequeña parte de esta piscina de hilo. Threadpoolexecutor es muy escalable, pero la premisa de extenderlo es estar familiarizado con cómo funciona. El siguiente artículo explicará cómo extender la clase ThreadPoolExeCutor.
La clase AVA.UTIL.CONCURRENT.THREADPOOLEXECUTOR proporciona una rica extensibilidad. Puede personalizar su comportamiento creando su subclase. Por ejemplo, quiero imprimir un mensaje después de que termine cada tarea, pero no puedo modificar el objeto de tarea, luego puedo escribir esto:
ThreadPoolExeCutor Ejecutor = new ThreadPoolExeCutor (size, maxSize, 1, TimeUnit.days, cola) {@Override void void AfterExecute (runnable r, t hrowable t) {system.out.println ("tarea terminada");
Además del método After Execute, la clase ThreadPoolExeCutor también tiene métodos antes de EXTEREXECUTE () y terminado () que se pueden anular, que se ejecutan antes de que se ejecute la tarea y después de que se detenga todo el grupo de subprocesos.
Además de agregar acciones antes y después de que se ejecutan las tareas, ThreadPoolExecutor también le permite personalizar la política de ejecución después de agregar tareas falla. Puede llamar al método setRejectedExecutionHandler () del grupo de subprocesos y reemplazar la política existente con el objeto Custom RechleedExeCutionHandler. ThreadPoolExecutor proporciona 4 políticas existentes, a saber:
Threadpoolexecutor.abortpolicy: indica que la tarea se rechaza y se lanza la excepción
Threadpoolexecutor.discardPolicy: significa rechazar la tarea pero no hacer ninguna acción
ThreadPoolExecutor.CallerrunSpolicy: indica que la tarea se rechaza y la tarea se ejecuta directamente en el hilo de la persona que llama.
ThreadPoolExecutor.DiscardoldestPolicy: significa que la primera tarea en la cola de tareas se descarta primero, y luego la tarea se agrega a la cola.
Aquí hay un ejemplo:
ThreadPoolExeCutor Ejecutor = new ThreadPoolExecutor (Size, MaxSize, 1, TimeUnit.days, cola);
Ejecutor.setRejedEdExecutionHandler (new ThreadPoolExeCutor.DiscoDPolicy ());
Además, también puede escribir sus propias políticas implementando la interfaz RecheedEdExecutionHandler. Aquí hay un ejemplo:
ThreadPoolExeCutor Ejecutor = new ThreadPoolExeCutor (3, 6, 1, TimeUnit.Seconds, Queue, New RecheedExecutionHandler () {public void RecheedDeDExecuti en (runnable r, threadpoolexecutor ejecutor) {system.out.println (string.format ("tarea %d rechazada rechazada rechazada .. "hhashcode ()));}});