Récemment, j'ai rencontré une nouvelle exigence dans le projet, qui est d'implémenter une fonction qui peut ajouter dynamiquement des tâches chronométrées. En parlant de cela, certaines personnes peuvent dire que c'est simple, utilisez simplement du quartz, c'est simple et grossier. Cependant, le cadre de quartz est trop lourd et les petits projets ne sont pas faciles à utiliser. Bien sûr, certaines personnes peuvent dire que JDK fournit une interface temporaire, ce qui est complètement suffisant. Cependant, les exigences de notre projet sont des modèles entièrement multi-thread, tandis que la minuterie est unique, donc, et l'auteur a finalement choisi le pool de fil de JDK.
Qu'est-ce qu'une piscine de fil
Java fournit quatre types de pools de fil par le biais d'exécuteurs, à savoir:
NewCachedThreadpool: Créez une piscine de threads cacheable. Si la longueur du pool de fils dépasse les besoins de traitement, vous pouvez recycler flexiblement les threads inactifs. S'il n'y a pas de recyclage, créez un nouveau fil.
NewFixEdThreadPool: Crée un pool de threads de longueur fixe qui peut contrôler le nombre maximum de threads concurrencés, et les threads excédentaires attendront dans la file d'attente.
NewsCheDuleDThreadPool: crée un pool de threads de longueur fixe qui prend en charge l'exécution de tâches chronométrée et périodique.
NewsingLetHreAdExEcutor: Crée un pool de threads unique, qui n'utilisera qu'un thread de travailleur unique pour exécuter des tâches, en veillant à ce que toutes les tâches soient exécutées dans l'ordre spécifié (FIFO, LIFO, priorité).
L'affiche utilise NewsCheDuledThreadpool dans le projet. C’est tout. Peu importe le nombre d'affiches, vous montrerez vos compétences. Google et c'est beaucoup.
Obtenir un service de pool de fil
L'auteur utilise le mode Singleton pour obtenir le service du pool de threads. Le code est le suivant:
/ ** * Création de piscine de fil. * @author wuhf * @date 2018/01/16 * / classe publique ThreadPoolUtils {private static scheduledexECUTORService ExecutorService; ThreadPoolUtils privé () {// Créer manuellement Pool Thread. ExecutorService = new scheduledThreadPoolExecutor (10, new BasicThreadFactory.Builder (). NamingPattern ("SyncData-Schedule-Pool-% d"). Daemon (true) .build ()); } classe statique privée PluginConfigholder {Instance statique finale statique finale Private = new ThreadPoolUtils (); } public static threadpoolutils getInstance () {return pluginConfigholder.instance; } public ScheduleDexeCutOrService getThreadpool () {return ExecutorService; }}Interrompre une implémentation de code de thread en cours d'exécution
Je ne dirai pas beaucoup de bêtises, le code est le suivant:
/ ** * Une tâche dans le pool de threads est interrompue. * / classe publique InterruptThread implémente Runnable {private int num; InterruptThread Public (int num) {this.num = num; } public static void main (String [] args) lève InterruptedException {thread interruptThread = new Thread (new interruptThread (1)); ScheduledFuture <?> T = ThreadPoolUtils.getInstance (). GetThreadpool (). ScheduleAtFixeDrate (InterruptThread, 0,2, timeunit.seconds); InterruptHead InterruptThread1 = new interruptThread (2); ThreadPoolUtils.getInstance (). GetThreadpool (). ScheduleAtFixeDrate (interruptThread1,0,2, timeUnit.seconds); InterruptThead InterruptThread2 = new interruptThread (3); Threadpoolutils.getInstance (). GetThreadpool (). ScheduleAtFixeDrate (interruptThread2,0,2, timeunit.seconds); Thread.sleep (5000); // terminer le fil de filetage en fonctionnement interruption t.cancel (true); while (true) {}} @Override public void run () {System.out.println ("Ceci est un thread" + num); }}Record piégé
Lorsque l'affiche utilisait le code suivant, il a soudainement réfléchi à la façon d'empêcher le fil d'exécution lorsque cette tâche de synchronisation doit être arrêtée.
ThreadPoolUtils.getInstance (). GetThreadpool (). ScheduleAtFixeDrate (InterruptThread, 0,2, timeunit.seconds);
Depuis que j'ai un tel besoin, Go sur Google. Après avoir cherché la plupart du temps, je n'ai trouvé aucune information pertinente. Ils étaient tous une analyse approfondie du pool de fils Java. Ou des variables globales ou quelque chose, aucune solution n'a été trouvée pour satisfaire l'auteur.
Puisqu'il n'y a pas de fil, jetons un coup d'œil au code source sous-jacent de ScheduleAtFixeDrate pour voir de quoi il s'agit. Comme prévu, j'ai vu l'implémentation spécifique de la méthode ScheduleAtFixeDrate dans le code source et j'ai constaté que sa valeur de retour est planifiée.
public ScheduledFuture <?> ScheduleAtFixeDrate (Commande Runnable, Long InitialDelay, longue période, Unit TimeUnit) {if (Command == NULL || UNIT == NULL) Lancez New NullPointerException (); if (période <= 0) lancer un nouveau IllégalArgumentException (); SchedouledFutureTask <Void> sft = new ScheduledFutureTask <foid> (commande, null, trigerTime (initialDelay, unit), unit.Tonanos (période)); RunnablesCheDuledFuture <foid> t = décorateTask (commande, sft); sft.outertask = t; DelayEdExECUTE (T); retour t; }Ensuite, jetons un coup d'œil à ce qui se trouve à l'intérieur de la fin de programmation. Ça n'a pas déçu l'affiche, et j'ai vu ça
public booléen annule (boolean MayInterrupfrunning) {booléen annulé = super.cancel (MayInterrupfrunning); if (annuled && disantOnCancel && heapindex> = 0) supprimer (this); return annulé;} // Supprimer le thread actuel de la file d'attente du thread booléen booléen de suppression (tâche de runnable) {boolean supprime = workQueue.Remove (tâche); TryTratiner (); // En cas d'arrêt et maintenant le retour vide supprimé;}Vérifions ce qu'est Super.Cancel (MayInterrupTifrunning). Nous voyons cela.
// Arrête le thread en cours d'exécution en appelant la méthode d'interruption du thread public booléen annule (boolean peut-ilterruptifrunning) {if (! (State == new && danged.comparandswapint (this, stateOffset, new, mayterrupfrunning? Interrupting: annuled))) return false; essayez {// dans le cas de l'appel pour interrompre les lancers exception if (MayInterrupfrunning) {try {Thread t = Runner; if (t! = null) t.interrupt (); } Enfin {// Final State Usadep.putOrderEDInt (this, StateOffset, interrompu); }}} enfin {fini finalCletion (); } return true; }Tous les problèmes ici sont résolus.
Résumons
Il existe toujours des solutions difficiles dans les projets. Lorsque Google n'est pas facile à trouver, cela peut être un bon moyen de rechercher le code source de JDK.