Le coût du démarrage d'un fil dans le système est relativement élevé car il implique une interaction avec le système d'exploitation. L'avantage d'utiliser un pool de threads est d'améliorer les performances. Lorsque le système contient un grand nombre de threads simultanés, il entraînera une forte baisse des performances du système et entraînera même une plantation de JVM. Le nombre maximum de threads dans le paramètre de pool de threads peut contrôler le nombre de threads simultanés dans le système pour ne pas dépasser le nombre de fois.
1. La classe d'usine des exécuteurs est utilisée pour générer un pool de threads . Cette classe d'usine contient les méthodes d'usine statiques suivantes pour créer le pool de threads correspondant. Le pool de threads créé est un objet ExecutorService. La méthode de soumission de l'objet ou exécuter la méthode pour exécuter les tâches exécutables ou appelables correspondantes. Le pool de threads lui-même appelle la méthode Shutdown () pour arrêter le pool de threads lorsqu'il n'est plus nécessaire. Après avoir appelé la méthode, le pool de threads n'autorisera plus les tâches à ajouter, mais ne mourra pas tant que toutes les tâches ajoutées n'auront pas été exécutées.
1. NewCachedThreadPool () crée un pool de threads avec une fonction de mise en cache et soumet le thread créé par la tâche (objet Runnable ou appelable) du pool de threads. Si l'exécution est terminée, elle sera mise en cache dans le CacheThreadpool pour l'utilisation des tâches qui doivent être exécutées ultérieurement.
Importer java.util.concurrent.execcutorService; Importer java.util.concurrent.execUtors; public class CacheThreadpool {static class taste implémente runnable {@Override public void run () {System.out.println (this + "" + threintHe Thread.currentThread (). GetAllStackTraces (). Size ()); }} public static void main (String [] args) {EMMIRCORORSSERVICE cacheThreadpool = exécutors.newcachedThreadpool (); // Ajoutez d'abord trois tâches au pool de threads pour (int i = 0; i <3; i ++) {cacheThreadpool.ExECUTE (new tâche ()); } // Une fois les trois threads exécutés, ajoutez à nouveau trois tâches au pool de thread, essayez à nouveau {Thread.Sleep (3000); } catch (InterruptedException e) {e.printStackTrace (); } pour (int i = 0; i <3; i ++) {cacheThreadpool.Execute (new task ()); }}}Les résultats de l'exécution sont les suivants:
Cachethreadpool $ tâche @ 2d312eb9 pool-1-thread-1 allStackTraces Taille de la carte: 7CachethReadpool $ tâche @ 59522b86 Pool-1-thread-3 allStackTraces Taille de la carte: 7CacheTheadpool $ tâche @ 73dbb89f pool-1-thread-2 Pool-1-thread-3 AllStacktraces Taille de la carte: 7CachethReadpool $ Task @ 256d5600 Pool-1-thread-1 AllStackTraces Taille de la carte: 7CachethReadpool $ Task @ 7D1C5894 Pool-1-thread-2 allstacktraces Taille de la carte: 7
Les objets de fil dans le pool de threads sont mis en cache et réutilisés lorsque de nouvelles tâches sont exécutées. Cependant, s'il y a beaucoup de concurrence, le pool de threads de cache créera toujours de nombreux objets de thread.
2. NewFixEdThreadpool (int nThreads) crée un pool de threads avec un nombre spécifié de threads qui peuvent être réutilisés par les threads.
Importer java.util.concurrent.executorService; Importer java.util.concurrent.execUtors; public class fixeThreadpool {static class taste implémente runnable {@Override public void run () {System.out.println (ce + "" + threinthared (). Thread.currentThread (). GetAllStackTraces (). Size ()); }} public static void main (String [] args) {EMECTRORORSERVICE FIXETHREADPOOL = EMICATORS.NEWFIXEDTHREADPOOL (3); // Ajoutez d'abord trois tâches au pool de threads pour (int i = 0; i <5; i ++) {fixeThreadpool.ExECUTE (new tâche ()); } // Une fois les trois threads exécutés, ajoutez à nouveau trois tâches au pool de thread, essayez à nouveau {Thread.Sleep (3); } catch (InterruptedException e) {e.printStackTrace (); } pour (int i = 0; i <3; i ++) {fixeTreadpool.ExECUTE (new task ()); }}}Résultats de l'exécution:
FIXTHREADPOOL $ TASSE @ 7045C12D Pool-1-thread-2 AllStackTraces Taille de la carte: 7FixEdThreadpool $ Task @ 50FA0BEF Pool-1-thread-2 AllStackTraces Taille de la carte: 7FixEdThreadpool $ Task @ CCB1870 Pool-1-thread-2 AllStackTraces Taille: 7FixEdThread-1 AllStackTraces Taille de la carte: 7FixEdThreadpool $ task @ 5BDEFF18 Pool-1-thread-2 AllStackTraces Taille de la carte: 7FixEdThreadpool $ task @ 7d5554e1 Pool-1-thread-1 AllStackTraces Taille: 7FixEdThreadpool $ Task @ 24468092 Pool-1-thread-3 AllStackTraces 7FixEdThreadpool $ tâche @ FA7B978 Pool-1-thread-2 AllStacktraces Taille de la carte: 7
3. NewsingLetHreAdExecutor (), créez un pool de threads avec seulement des threads uniques, ce qui équivaut à appeler newFixEdThreadPool (1)
4. NewSheduleDThreadPool (int corepoolSize), crée un pool de threads avec un nombre spécifié de threads, qui peuvent exécuter des threads après un retard spécifié. Vous pouvez également répéter un fil dans une certaine période, sachant que vous pouvez appeler Shutdown () pour fermer le pool de threads.
Les exemples sont les suivants:
Importer java.util.concurrent.executors; importer java.util.concurrent.scheduleExECUTORService; import java.util.concurrent.timeUnit; classe publique scheduledTheredpool {static class tâche implémente runnable {@Override public Void run () {System.out.printLnn ("Time" + System + "" + Thread.currentThread (). GetName () + "AllStackTraces Taille de la carte:" + thread.currentThread (). GetAllStackTraces (). Size ()); }} public static void main (String [] args) {ScheduleDExECUTORService scheduleDexeCutOrService = exécutor.newScheduleDThreadPool (3); ScheduleDExECUtorService.Schedule (new task (), 3, timeunit.seconds); ScheduleDExECUTORService.ScheduleAtFixeDrate (new Task (), 3, 5, timeunit.seconds); essayez {thread.sleep (30 * 1000); } catch (InterruptedException e) {e.printStackTrace (); } ScheduleDExECUtOrService.shutdown (); }}Les résultats de l'opération sont les suivants:
Temps 1458921795240 Pool-1-thread-1 AllStackTraces Taille de la carte: 6time 1458921795241 Pool-1-thread-2 AllStackTraces Taille: 6time 1458921800240 Pool-1-thread-1 AllstackTraces Map Taille: 7time 1458921805240 POOL-1-TRADE-1 1458921810240 Pool-1-thread-1 AllStackTraces Taille de la carte: 7time 1458921815240 Pool-1-thread-1 AllStacktraces Taille de la carte: 7 fois 1458921820240 Pool-1-thread-1 allstacktraces Taille de la carte: 7
Comme le montre le temps d'exécution, la tâche est exécutée dans un cycle de 5 secondes.
5. NewsingLeTheReadScheduleDexecutor () crée un pool de fil avec un seul fil et appelle NewscheduleDtHreadPool (1).
2. Forkjoinpool et fourkjointask
Forkjoinpool est une classe d'implémentation de ExecutorService. Il prend en charge la division d'une tâche en plusieurs petites tâches en calcul parallèle et combinant les résultats de calcul de plusieurs petites tâches dans les résultats du calcul total. Il a deux constructeurs
Forkjoinpool (int parallélisme) crée un forkjoinpool qui contient des fils de parallélisme.
FORKJOINPOOL (), crée ForkJoinpool en utilisant la valeur de retour de la méthode Runtime.VailableProcessors () comme paramètre de parallélisme.
FORKJOINTASK représente une tâche qui peut être parallèle et fusionnée. Il s'agit d'une classe abstraite qui implémente l'interface future <T>. Il dispose de deux sous-classes abstraites, représentant la recursue de la tâche sans valeur de retour et le récursiveTask avec une valeur de retour. Vous pouvez hériter de ces deux classes abstraites en fonction des besoins spécifiques pour implémenter vos propres objets, puis appeler la méthode de soumission de ForkJoinpool à exécuter.
L'exemple de récurivation est le suivant, implémentant des sorties parallèles de 0-300 nombres.
import java.util.concurrent.forkjoinpool; import java.util.concurrent.recursiveAction; import java.util.concurrent.timeunit; classe publique ActionForkJointask {classe statique printask étend récursiveAction {private static final int threshold = 50; Int privé Start; Int privé End; public printTask (int start, int end) {this.start = start; this.end = end; } @Override Protected void compute () {if (end - start <threshold) {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); Left.Fork (); droite.Fork (); }}} public static void main (String [] args) {forkjoinpool pool = new forkjoinpool (); Pool.Submit (nouveau PrintTask (0, 300)); essayez {pool.awampitring (2, timeunit.seconds); } catch (InterruptedException e) {e.printStackTrace (); } pool.shutdown (); }}Après avoir divisé la petite tâche, appelez la méthode Fork () de la tâche et ajoutez-la à la forkjoinpool pour l'exécution en parallèle.
RecursiveTask Exemple, met en œuvre un calcul parallèle de 100 entiers à résumer. Divisez-vous tous les 20 numéros et additionnez-les pour obtenir le résultat, et fusionnez-les dans le résultat final à la fin.
Importer java.util.random; Importer java.util.concurrent.executionException; import java.util.concurrent.forkjoinpool; import java.util.concurrent.future; import java.util.concurrent.recursiveTask; Public Class TaskForkjoint {STATIC CLASSE CALLTASK étend Recursiven <INTERFORKJOINTAK {STATIC CLASSE CALLTASK étend Recursask <INTERFORKJOINGS {STATIC CLASSE CALLTASK étend Recursivet <INTERFORKJOING {STATIC CLASSE CALLTASS Seuil Int final statique privé = 20; INTR ARRT PRIVÉ []; Int privé Start; Int privé End; public caltask (int [] arr, int start, int end) {this.arr = arr; this.start = start; this.end = end; } @Override Protected Integer Compute () {int sum = 0; if (end - start <threshold) {for (int i = start; i <end; i ++) {sum + = arr [i]; } System.out.println (thread.currentThread (). GetName () + "sum:" + sum); somme de retour; } else {int middle = (start + end) / 2; Caltask Left = new Caltask (arr, start, middle); Caltask Right = new Caltask (arr, milieu, fin); Left.Fork (); droite.Fork (); return gauche.join () + droit.join (); }}} public static void main (String [] args) {int arr [] = new int [100]; Aléatoire aléatoire = nouveau aléatoire (); 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 = new ForkJoinpool (4); Future <Integer> futur = pool.submit (new Caltask (arr, 0, arr.length)); essayez {System.out.println ("Résultat cal:" + futur.get ()); } catch (InterruptedException e) {e.printStackTrace (); } catch (EXECUTUTIONException) e) {e.printStackTrace (); } pool.shutdown (); }}Les résultats de l'exécution sont les suivants:
Total 912ForkJoinpool-1-Locker-2 Somme: 82Forkjoinpool-1-Lavorker-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 Somme: 121Forkjoinpool-1-Laveuse-3 Somme: 89cal Résultat: 912
Une fois la sous-tâche exécutée, appelez la méthode join () de la tâche pour obtenir le résultat d'exécution de la sous-tâche, puis ajoutez-le pour obtenir le résultat final.