1. Présentation
Implémentation de la fonction d'exécuter régulièrement des tâches en Java, en utilisant principalement deux classes, des classes TIMER et TIMERTASK. La minuterie est utilisée pour exécuter des tâches spécifiées dans un thread d'arrière-plan en fonction du plan spécifié.
Timertask est une classe abstraite, et sa sous-classe représente une tâche qui peut être planifiée par la minuterie. Le code spécifique à exécuter est écrit dans la méthode d'exécution selon laquelle Timertask doit être implémenté.
2. Jetons un coup d'œil à l'exemple le plus simple
Expliquons-le via le code
import java.text.simpledateFormat; import java.util.date; import java.util.timer; import java.util.timertask; public class timerDemo {public static string getCurrentTime () {date date = new Date (); SimpledateFormat sdf = new SimpledateFormat ("yyyy-mm-dd hh: mm: ss"); return sdf.format (date); } public static void main (String [] args) lève InterruptedException {System.out.println ("start principal:" + getCurrentTime ()); startTimer (); Thread.Sleep (1000 * 5); // Dormez pendant 5 secondes System.out.println ("End principal:" + GetCurrentTime ()); } public static void startImmer () {Timertask task = new Timemertask () {@Override public void run () {System.out.println ("tâche Run:" + GetCurrentTime ()); }}; Timer Timer = new Timer (); timer.schedule (tâche, 0); }}Afin de faciliter les informations d'observation en imprimant, nous avons ajouté des informations d'impression à la méthode principale et appelée thread.SOep pour faire dormir le fil principal. De plus, une méthode GetCurrentTime est ajoutée à la classe pour obtenir la date actuelle.
Dans le code ci-dessus, dans la méthode StartTimer, un objet Tirmertask (la tâche à exécuter par la minuterie) est créée, et un objet Timer est créé, et la méthode de planification de la classe de minuterie est appelée. La classe de minuterie a plusieurs méthodes de planification avec différents paramètres. Ce qui est utilisé ici est:
Horaire du vide public (tâche Timetask, long retard)
La signification de cette méthode est d'exécuter la tâche de tâche après que le temporisateur retardera le temps (millisecondes). Si le retard est négatif ou 0, la tâche sera effectuée immédiatement. Et il s'agit d'une tâche d'exécution unique, et la tâche ne sera pas répétée (ou planifiée) par la suite.
Pour la classe de minuterie, une méthode avec la même fonction est également fournie, comme suit:
Horaire du vide public (tâche Timemeras, heure de date)
La différence entre cette méthode et la méthode ci-dessus est que la méthode ci-dessus spécifie que l'exécution est retardée pendant une période de temps, et cette méthode spécifie que l'exécution est effectuée à un moment spécifique. Notez que si l'heure actuelle du système a dépassé le temps spécifié par l'heure du paramètre, la tâche sera exécutée immédiatement.
Lors de l'exécution du code ci-dessus, nous avons constaté que le programme imprime immédiatement deux informations similaires à ce qui suit:
Démarrage principal: 2016-01-13 22:23:18
Exécution des tâches: 2016-01-13 22:23:18
Étant donné que la valeur du paramètre de retard que nous passons à la méthode de planification ici est 0, la tâche sera exécutée immédiatement, donc l'heure d'impression des deux instructions est la même, ce qu'elle devrait être. Vous pouvez modifier vous-même la valeur de retard entrant pour voir les modifications des informations de sortie. Après environ 5 secondes (c'est-à-dire le temps de sommeil), j'ai continué à imprimer 1 message:
Fin principal: 2016-01-13 22:23:23
Le temps pour l'impression est de 5 secondes en deçà de l'énoncé ci-dessus, ce qui est conforme au réglage du sommeil, ce qui est également très raisonnable.
Mais nous trouverons un phénomène très intéressant, et nous constaterons que le processus ne sortira pas. À l'heure actuelle, le fil principal principal est terminé. Cela signifie qu'après avoir terminé la tâche, même s'il n'y a pas de tâches qui attendent d'être exécutées plus tard, le thread d'arrière-plan créé dans la minuterie ne sortira pas immédiatement. J'ai vérifié la documentation du DOC Java pertinente et expliqué que le fil de minuterie ne sortait pas activement et doit attendre la collecte des ordures, mais la collection de déchets de Java ne peut pas être contrôlée par le code lui-même, mais il est contrôlé par la machine virtuelle.
Après la recherche, il a été constaté que lors de la création d'un objet de minuterie et de l'exécution du minuteur de minuterie = new Timer (); Instruction, le thread de minuterie sera créé. En d'autres termes, même si le code ci-dessus n'a pas le Timer.Schedule (tâche, 0); déclaration, le programme ne sortira pas. Je pense que c'est assez déraisonnable. J'ai à nouveau étudié le code source de la classe de minuterie et j'ai constaté qu'il dispose également d'un constructeur avec des paramètres booléens:
Minuterie publique (Boolean Isdaemon)
Comme vous pouvez le voir sur le nom du paramètre, si la valeur du paramètre est vraie, le thread de minuterie créé par la minuterie est le thread de démon. La signification d'un fil de démon est que lorsque tous les fils de travail dans la sortie du processus Java, le thread de démon sortira automatiquement.
Pour le moment, nous avons juste besoin de modifier le code pour créer l'objet Timer dans l'exemple ci-dessus en: Timer Timer = new Timer (true);
Après avoir constaté que le programme est exécuté, le programme sortira après le thread principal (le thread principal n'est pas un thread de démon, mais un fil de travail) est terminé, ce qui signifie que le thread de minuterie quitte également, ce qui signifie qu'après avoir ajouté le paramètre vrai, le thread de démon créé est le thread de démon.
Mais le problème est que dans les scénarios d'application réels, il existe de nombreux threads de travail et que le programme ne sorta pas avec désinvolture. Et si vous voulez que la minuterie sorte ou ferme immédiatement? Nous le présenterons ci-dessous.
3. Exit de minuterie
La classe de minuterie fournit une méthode d'annulation pour annuler le minuteur. L'appel de la méthode d'annulation mettra fin à cette minuterie et jette toutes les tâches actuellement planifiées. Cela n'interfère pas avec la tâche en cours d'exécution (s'il existe). Une fois la minuterie terminée, son thread d'exécution se terminera également et aucune tâche ne peut être planifiée en fonction de celle-ci.
Notez qu'en appelant cette méthode dans la méthode d'exécution de la tâche de temporisation appelée ce temporisateur, vous pouvez absolument vous assurer que la tâche exécutée est la dernière tâche exécutée par ce temporisateur. Cette méthode peut être appelée à plusieurs reprises; Cependant, les deuxièmes appels et suivants ne sont pas valides.
Regardons un autre exemple de code:
import java.text.simpledateFormat; import java.util.date; import java.util.timer; import java.util.timertask; public class timerDemo {public static string getCurrentTime () {date date = new Date (); SimpledateFormat sdf = new SimpledateFormat ("yyyy-mm-dd hh: mm: ss"); return sdf.format (date); } public static void main (String [] args) lève InterruptedException {System.out.println ("start principal:" + getCurrentTime ()); Timer Timer = startTimer (); Thread.Sleep (1000 * 5); // Dormez pendant 5 secondes System.out.println ("End principal:" + GetCurrentTime ()); timer.cancel (); } public static timer startTimer () {TIMERTASK Task = new Timertask () {@Override public void run () {System.out.println ("tâche Run:" + GetCurrentTime ()); }}; Timer Timer = new Timer (); timer.schedule (tâche, 0); temporisateur de retour; }} L'exécution du programme est exactement la même que la sortie de l'exemple ci-dessus. La différence est que lorsque la méthode principale se termine. Le processus sortira activement, ce qui signifie que le thread de minuterie a été fermé.
Parce que nous appelons la méthode d'annulation dans la méthode principale. Notez que si vous n'appelez pas la méthode Annuler dans la méthode d'exécution de Timertask, assurez-vous de vous assurer que la tâche que vous souhaitez exécuter a démarré ou terminé, sinon si la tâche n'a pas commencé à s'exécuter. Appelez simplement Annuler et toutes les tâches ne seront pas exécutées. Par exemple, le code ci-dessus,
Par exemple, dans le code ci-dessus, si nous n'appelons pas la méthode d'annulation dans la méthode principale, mais ajoutez le Timer.Schedule (tâche, 0); instruction dans la méthode startTimer et ajoutez le timer.cancel (); Instruction Après l'exécution, vous constaterez que la tâche du temporisateur ne sera pas exécutée, car elle sera annulée avant la fin de l'exécution.
4. Exécuter régulièrement des tâches
Dans l'exemple ci-dessus, nous introduisons une tâche unique, c'est-à-dire que le temps de la minuterie est venu. Une fois la tâche exécutée, elle ne sera pas répétée plus tard. Dans les applications réelles, il existe de nombreux scénarios qui nécessitent que la même tâche soit exécutée régulièrement à plusieurs reprises. Il y a deux situations: l'une consiste à exécuter des tâches de temps en temps, et l'autre consiste à effectuer des tâches à un certain (ou plusieurs) points de temps chaque jour (ou hebdomadaire, mensuel, etc.).
Examinons d'abord le premier cas, qui est un exemple de l'exécution de la même tâche toutes les 10 secondes. Le code est le suivant:
import java.text.simpledateFormat; import java.util.date; import java.util.timer; import java.util.timertask; public class timerDemo {public static string getCurrentTime () {date date = new Date (); SimpledateFormat sdf = new SimpledateFormat ("yyyy-mm-dd hh: mm: ss"); return sdf.format (date); } public static void main (String [] args) lève InterruptedException {System.out.println ("start principal:" + getCurrentTime ()); startTimer (); } public static void startImmer () {Timertask task = new Timemertask () {@Override public void run () {System.out.println ("tâche Run:" + GetCurrentTime ()); essayez {thread.sleep (1000 * 3); } catch (InterruptedException e) {e.printStackTrace (); }}}; Timer Timer = new Timer (); timer.schedule (tâche, 1000 * 5,1000 * 10); }} Exécutez le programme ci-dessus et les informations de sortie sont les suivantes (car le temporisateur ne s'arrête pas et que la tâche est répétée, la sortie sera en continu. Seules certaines des sorties précédentes sont copiées ici)
Démarrage principal: 2016-01-14 08:41:14
Exécution de la tâche: 2016-01-14 08:41:19
Exécution de la tâche: 2016-01-14 08:41:29
Exécution de la tâche: 2016-01-14 08:41:39
Exécution de la tâche: 2016-01-14 08:41:49
Exécution de la tâche: 2016-01-14 08:42:00
Exécution de la tâche: 2016-01-14 08:42:10
Exécution des tâches: 2016-01-14 08:42:20
Exécution de la tâche: 2016-01-14 08:42:30
Exécution de la tâche: 2016-01-14 08:42:40
Dans le code ci-dessus, nous appelons Timer.Schedule (tâche, 1000 * 5,1000 * 10); Cela signifie que la tâche est retardée de 5 secondes, puis elle sera répétée toutes les 10 secondes. Nous observons que le temps d'impression dans les informations de sortie est le même que prévu. De plus, on peut voir que l'intervalle est calculé en fonction de l'heure de début de la tâche, c'est-à-dire qu'il ne s'agit pas d'attendre encore 10 secondes après la fin de la tâche.
La classe TIMER a deux méthodes pour implémenter de telles fonctions, comme suit:
Horaire de vide public (tâche Timetask, long retard, longue période) Public Void Schecale (tâche Tirmertask, date de première fois, longue période)
La première méthode que nous utilisons ci-dessus du code. La différence entre les deux méthodes est le temps de la première exécution. La première méthode est exécutée après un délai spécifié d'une période de temps (en millisecondes); La deuxième méthode est exécutée à un point temporel spécifié.
Pour le moment, nous considérons le scénario suivant. Si le temps d'exécution d'une tâche dépasse le prochain temps d'attente, que se passera-t-il? Regardons-le à travers le code:
import java.text.simpledateFormat; import java.util.date; import java.util.timer; import java.util.timertask; public class timerDemo {public static string getCurrentTime () {date date = new Date (); SimpledateFormat sdf = new SimpledateFormat ("yyyy-mm-dd hh: mm: ss"); return sdf.format (date); } public static void main (String [] args) lève InterruptedException {System.out.println ("start principal:" + getCurrentTime ()); startTimer (); } public static void startImmer () {Timertask task = new Timemertask () {@Override public void run () {System.out.println ("tâche Begin:" + GetCurrentTime ()); essayez {thread.sleep (1000 * 10); } catch (InterruptedException e) {e.printStackTrace (); } System.out.println ("Task End:" + GetCurrentTime ()); }}; Timer Timer = new Timer (); timer.schedule (tâche, 1000 * 5,1000 * 5); }} Par rapport au code précédent, nous n'avons changé que 2 codes et modifié l'impression. L'un consiste à changer le sommeil dans la méthode d'exécution à 10 secondes, et l'autre consiste à modifier le cycle d'exécution de la tâche à 5 secondes. En d'autres termes, le temps d'exécution de la tâche dépasse l'intervalle entre l'exécution répétée de la tâche. Exécutez le programme, la sortie précédente est la suivante:
Démarrage principal: 2016-01-14 09:03:51
Début de la tâche: 2016-01-14 09:03:56
Tâche fin: 2016-01-14 09:04:06
Début de la tâche: 2016-01-14 09:04:06
Tâche fin: 2016-01-14 09:04:16
Début de la tâche: 2016-01-14 09:04:16
Tâche fin: 2016-01-14 09:04:26
Début de la tâche: 2016-01-14 09:04:26
Tâche fin: 2016-01-14 09:04:36
Début de la tâche: 2016-01-14 09:04:36
Tâche fin: 2016-01-14 09:04:46
Début de la tâche: 2016-01-14 09:04:46
Tâche fin: 2016-01-14 09:04:56
On peut voir qu'après l'exécution de chaque tâche, la tâche suivante sera exécutée immédiatement. Étant donné que le temps pris du début de la tâche à l'achèvement de la tâche a dépassé l'intervalle entre la répétition de la tâche, l'exécution sera répétée.
5. Exécuter régulièrement les tâches (répéter le point de temps fixe)
Implémentez une telle fonction, effectuons régulièrement une tâche à 1 h du matin tous les jours, qui a cette fonction dans de nombreux systèmes, tels que la réalisation de tâches qui prennent du temps et consommées par les ressources telles que la sauvegarde des données et les statistiques de données dans cette tâche. Le code est le suivant:
import java.text.simpledateFormat; import java.util.calendar; import java.util.date; import java.util.timer; import java.util.timertask; public class timerdemo {public static static getCurrentTime () {date date = new Date (); SimpledateFormat sdf = new SimpledateFormat ("yyyy-mm-dd hh: mm: ss"); return sdf.format (date); } public static void main (String [] args) lève InterruptedException {System.out.println ("start principal:" + getCurrentTime ()); startTimer (); } public static void startImmer () {Timertask task = new Timemertask () {@Override public void run () {System.out.println ("tâche Begin:" + GetCurrentTime ()); essayez {thread.sleep (1000 * 20); } catch (InterruptedException e) {e.printStackTrace (); } System.out.println ("Task End:" + GetCurrentTime ()); }}; Timer Timer = new Timer (); timer.schedule (tâche, buildtime (), 1000 * 60 * 60 * 24); } private static date buildtime () {calendar calendar = calendar.getInstance (); calendar.set (calendar.hour_of_day, 1); calendar.set (calendar.minute, 0); calendar.set (calendar.second, 0); Date heure = calendar.getTime (); if (time.before (new Date ())) {// Si l'heure actuelle est après 1 h, 1 jour est nécessaire, sinon la tâche sera exécutée immédiatement. // De nombreux systèmes doivent souvent exécuter des tâches immédiatement lorsque le système commence, mais ils doivent les exécuter à 1 h du matin tous les jours. Que dois-je faire? // C'est très simple, exécutez simplement la tâche séparément lorsque le système initialise l'appel (aucun temporisateur n'est nécessaire, c'est juste le code pour exécuter cette tâche) Time = Addday (temps, 1); } Heure de retour; } Date statique privée Addday (date de date, jours int) {Calendar startdt = calendar.getInstance (); startdt.setTime (date); startdt.add (calendar.day_of_month, jours); return startdt.gettime (); }}Parce qu'il est exécuté à des intervalles de 24 heures, il est impossible d'attendre l'observation de la sortie.
6. Résumé
Cet article présente le mécanisme de la façon d'effectuer des tâches chronométrées à l'aide de la classe Java Timer. On peut voir qu'il existe encore de nombreuses façons de faire attention. Dans les exemples introduits dans cet article, chaque minuterie correspond à une seule tâche.
Le contenu introduit dans cet article peut répondre à la plupart des scénarios d'application, mais il y a encore des problèmes, tels que l'inclusion de plusieurs tâches pour une minuterie? Puis-je ajouter à nouveau des tâches après l'annulation de la minuterie? Quelles autres méthodes sont disponibles dans la classe TIMER? Ces questions seront introduites dans le billet de blog suivant.
Lien original: http://www.cnblogs.com/51kata/p/5128745.html
Ce qui précède est tout le contenu de cet article. J'espère que cela sera utile à l'apprentissage de tous et j'espère que tout le monde soutiendra davantage Wulin.com.