El costo de iniciar un hilo en el sistema es relativamente alto porque implica la interacción con el sistema operativo. La ventaja de usar un grupo de subprocesos es mejorar el rendimiento. Cuando el sistema contiene una gran cantidad de hilos concurrentes, causará una fuerte disminución en el rendimiento del sistema e incluso hará que JVM se bloquee. El número máximo de subprocesos en el parámetro del grupo de subprocesos puede controlar el número de subprocesos concurrentes en el sistema para no exceder el número de veces.
1. La clase de fábrica de ejecutores se usa para generar un grupo de subprocesos . Esta clase de fábrica contiene los siguientes métodos de fábrica estática para crear el grupo de subprocesos correspondiente. El grupo de subprocesos creado es un objeto EjecutorService. El método de envío del objeto o el método de ejecución para ejecutar las tareas ejecutables o convocables correspondientes. La piscina de hilo en sí llama al método apagado () para detener el grupo de subprocesos cuando ya no es necesario. Después de llamar al método, el grupo de subprocesos ya no permitirá agregar tareas, pero no morirá hasta que se hayan ejecutado todas las tareas agregadas.
1. NewCachedThreadPool () crea un grupo de subprocesos con la función de almacenamiento en caché y envía el hilo creado por la tarea (objeto ejecutable o llamable) del grupo de subprocesos. Si se completa la ejecución, se almacenará en caché en el CachedThreadPool para el uso de las tareas que deben ejecutarse más adelante.
import java.util.concurrent.executorservice; import java.util.concurrent.executors; public class CachethreadPool {Static Class Task Implements runnable {@Override public void run () {system.out.println (this + " + shiff.currentThread (). getname () +" Allstacktraces sea Thread.CurrentThread (). GetAllStAcktRaces (). Size ()); }} public static void main (string [] args) {ExecutorService CachethreadPool = Ejecutors.NewCachedThreadPool (); // Agregue tres tareas al grupo de subprocesos primero para (int i = 0; i <3; i ++) {CachethreadPool.execute (nueva tarea ()); } // Después de ejecutar los tres hilos, agregue tres tareas al grupo de subprocesos nuevamente, intente {Thread.sleep (3000); } catch (InterruptedException e) {E.PrintStackTrace (); } para (int i = 0; i <3; i ++) {CachethreadPool.execute (nueva tarea ()); }}}Los resultados de la ejecución son los siguientes:
Cachethreadpool $ tarea@2D312EB9 Pool-1-Thread-1 AllStackTRACES Tamaño del mapa: 7CachethEltPool $ tarea@59522b86 Pool-1-thread-3 AllStackTRACES Tamaño del mapa: 7CachethreadPool $ tarea@73DBB89F Pool-1-thread- Allacktraces Map size: 7CachethetPool $ tarea@57CeCECECECTCCOCCOFCOM-1-THREAD-2 AllackTraces Map Size: 7CachethetPool $ Task@57CeCECECECECCECT Pool-1-Thread-3 AllstackTraces Tamaño del mapa: 7cachethreadpool $ tarea@256d5600 Pool-1-Thread-1 AllStackTRACES Tamaño del mapa: 7cachethreadpool $ tarea@7D1C5894 Pool-1-Thread-2 Allstacktraces Tamaño del mapa: 7
Los objetos de hilo en el grupo de subprocesos se almacenan en caché y se reutilizan cuando se ejecutan nuevas tareas. Sin embargo, si hay mucha concurrencia, el grupo de subprocesos de caché aún creará muchos objetos de subprocesos.
2. NewFixedThreadPool (int nthreads) crea un grupo de hilos con un número especificado de hilos que pueden ser reutilizados por hilos.
import java.util.concurrent.executorservice; import java.util.concurrent.executors; public class FixedThreadPool {Static Class Task implementa runnable {@Override public void run () {System.out.println (this + " + Thread.CurrentThread (). Thread.CurrentThread (). GetAllStAcktRaces (). Size ()); }} public static void main (string [] args) {ExecutorService FixedThreadPool = Ejecutors.NewFixedThreadPool (3); // Primero agregue tres tareas al grupo de subprocesos para (int i = 0; i <5; i ++) {fixedThreadPool.execute (new Task ()); } // Después de ejecutar los tres hilos, agregue tres tareas al grupo de subprocesos nuevamente, intente {Thread.sleep (3); } catch (InterruptedException e) {E.PrintStackTrace (); } para (int i = 0; i <3; i ++) {fixthreadpool.execute (new Task ()); }}}Resultados de la ejecución:
Fijado de lecado $ tarea@7045C12d Pool-1-Thread-2 AllStackTraces Tamaño del mapa: 7fixedThreadPool $ tarea@50fa0bef Pool-1-Thread-2 AllStackTRACES Tamaño del mapa: 7fixedThreadPool $ tarea@CCB1870 Pool-1-Read. AllStackTraces Map tamaño: 7fixedThreadPool $ tarea@5BDeff18 Pool-1-Thread-2 AllStackTraces Tamaño del mapa: 7fixedThreadPool $ tarea@7D55554E1 Pool-1-thread-1 AllStackTraces Map tamaño del mapa: 7fixedThreadPool $ tarea@24468092 Pool-1-thread-3 Allstacktraces Map Size: 7fixedThreadPool $ tarea@FA7B978 Pool-1-Thread-2 AllStackTRACES Tamaño del mapa: 7
3. NewsingLethreadExecutor (), cree un grupo de hilos con solo hilos, que es equivalente a llamar a NewfixedThreadPool (1)
4. NewSheduledThreadPool (int corePoolSize), crea un grupo de subprocesos con un número especificado de subprocesos, que puede ejecutar subprocesos después de un retraso especificado. También puede repetir un hilo en un cierto período de tiempo, sabiendo que puede llamar a SHUTDOWN () para cerrar el grupo de hilos.
Los ejemplos son los siguientes:
import java.util.concurrent.executors; import java.util.concurrent.scheduledExeCutorService; import java.util.concurrent.timeunit; public class ScheduledThreadPool {Task de clase estática Implementa Runnable {@Override public Public run () {System.Println ("Time" Task Static Task Runnable {@Override public run () {System.out.Println ("Time" Task Static Task Runnable {@Override pública public run () {System.Println ("Time" Task Static Task Runnable {@Override public run () {System.out.Println ("Time" System.CurNTIMENT + "" + Thread.CurrentThread (). GetName () + "AllStackTraces Size:" + Thread.CurrentThread (). GetAllStAcktRaces (). Size ()); }} public static void main (string [] args) {ProgramedExecutorService ProchuledExecutorService = Ejecutors.NewScheduledThreadPool (3); ProchuledExecutorService.schedule (nueva tarea (), 3, TimeUnit.seconds); ProchuledExecutorService.schedleatFixedRate (nueva tarea (), 3, 5, TimeUnit.seconds); intente {Thread.sleep (30 * 1000); } catch (InterruptedException e) {E.PrintStackTrace (); } ProgramedExecutorService.shutdown (); }}Los resultados de la operación son los siguientes:
Tiempo 1458921795240 Pool-1-Thread-1 Allstacktraces Tamaño del mapa: 6Time 1458921795241 Pool-1-Thread-2 AllStackTraces Tamaño del mapa: 6Time 1458921800240 Pool-1-THREAD-1 Allstacktraces Tamaño del mapa: 7Time 1458921805240 Pool-1-Read-1 de referencia-1 de referencia 1 1458921810240 Pool-1-Thread-1 Allstacktraces Tamaño del mapa: 7Time 1458921815240 Pool-1-Thread-1 Allstacktraces Tamaño del mapa del mapa: 7 Tiempo 1458921820240 Pool-1-Porta-1 Tamaño del mapa de Allstacktraces: 7
Como se puede ver desde el tiempo de ejecución, la tarea se ejecuta en un ciclo de 5 segundos.
5. NewsingLethreadScheduledExecutor () crea un grupo de hilos con solo un hilo, y llama a NewsCheduledThreadPool (1).
2. Forkjoinpool y ForkJointask
Forkjoinpool es una clase de implementación de EjecutorService. Admite dividir una tarea en múltiples tareas pequeñas en la computación paralela, y combinar los resultados del cálculo de múltiples tareas pequeñas en los resultados totales de cálculo. Tiene dos constructores
Forkjoinpool (int paralelismo) crea un bifurcado que contiene hilos de paralelismo.
Forkjoinpool (), crea Forkjoinpool utilizando el valor de retorno de Runtime.availableProcessors () como el parámetro de paralelismo.
ForkJoNkask representa una tarea que puede ser paralela y fusionada. Es una clase abstracta que implementa la interfaz futura <t>. Tiene dos subclases abstractos, que representan la recuración de la tarea sin un valor de retorno y el recursivetask con un valor de retorno. Puede heredar estas dos clases de resumen de acuerdo con necesidades específicas para implementar sus propios objetos y luego llamar al método de envío de Forkjoinpool para ejecutar.
El ejemplo de recuración es el siguiente, implementando salidas paralelas de números 0-300.
import java.util.concurrent.forkjoinpool; import java.util.concurrent.recursiveaction; import java.util.concurrent.timeunit; publicidad de clase públicaForkJoinTask {Class estática PrintTask extiende recursos de recursos {private está final estático inthReshold = 50; Inicio privado int; Private int final; public printTask (int inicio, int end) {this.start = start; this.end = end; } @Override Protected void compute () {if (end - start <umbral) {for (int i = start; i <end; i ++) {system.out.println (thread.currentThread (). GetName () + "" + i); }} else {int middle = (start + end) / 2; PrintTask Left = new PrintTask (Start, Middle); PrintTask Right = new PrintTask (Middle, End); izquierda.fork (); right.fork (); }}} public static void main (string [] args) {forcjoinpool piscol = new Forkjoinpool (); Pool.submit (nueva printTask (0, 300)); intente {Pool.AwaitTermination (2, TimeUnit.seconds); } catch (InterruptedException e) {E.PrintStackTrace (); } prow.shutdown (); }}Después de dividir la pequeña tarea, llame al método Fork () de la tarea y agréguelo al ForkjoInpool para su ejecución en paralelo.
Ejemplo de recursivetask, implementa un cálculo paralelo de 100 enteros a suma. Dividen cada 20 números y suma para obtener el resultado, y fusionarlos en el resultado final al final.
import java.util.random; import java.util.concurrent.ExecutionException; import java.util.concurrent.forkoinpool; import java.util.concurrent.future; import java.util.concurrent.RecursivetaSk; public class TaskforkJoTask {Static Class Caltask Extends Extends umbral de intent intest de intratico privado = 20; private int arr []; Inicio privado int; Private int final; public caltask (int [] arr, int inicio, int end) {this.arr = arr; this.start = inicio; this.end = end; } @Override protegido Integer Compute () {int sum = 0; if (end - start <umbral) {for (int i = start; i <end; i ++) {sum+= arr [i]; } System.out.println (thread.currentThread (). GetName () + "suma:" + suma); suma de retorno; } else {int middle = (start + end) / 2; Caltask a la izquierda = nuevo Caltask (arr, inicio, medio); Caltask derecha = nueva caltask (arr, media, final); izquierda.fork (); right.fork (); return left.Join () + right.Join (); }}} public static void main (string [] args) {int arr [] = new int [100]; Aleatorio aleatorio = new Random (); int total = 0; for (int i = 0; i <arr.length; i ++) {int tmp = random.nextInt (20); total += (arr [i] = tmp); } System.out.println ("total" + total); Forkjoinpool Pool = nuevo Forkjoinpool (4); Future <Integer> Future = Pool.Submit (New Caltask (arr, 0, arr.length)); prueba {System.out.println ("Resultado cal:" + futuro.get ()); } catch (InterruptedException e) {E.PrintStackTrace (); } catch (ExecutionException) e) {E.PrintStackTrace (); } prow.shutdown (); }}Los resultados de la ejecución son los siguientes:
total 912ForkJoinPool-1-worker-2 sum:82ForkJoinPool-1-worker-2 sum:123ForkJoinPool-1-worker-2 sum:144ForkJoinPool-1-worker-3 sum:119ForkJoinPool-1-worker-2 sum:106ForkJoinPool-1-worker-2 sum:128ForkJoinPool-1-worker-2 Suma: 121forkoinpool-1-Worker-3 Suma: 89 RESULTADO DE CAL: 912
Después de ejecutar la subtarea, llame al método Join () de la tarea para obtener el resultado de ejecución de la subtarea, y luego agréguelo para obtener el resultado final.