107 votes

Timer & TimerTask versus Thread + sleep en Java

J'ai trouvé des questions similaires posées ici, mais je n'ai pas trouvé de réponses satisfaisantes. Donc, en reformulant la question à nouveau-

J'ai une tâche qui doit être effectuée à intervalles réguliers (disons toutes les minutes). Quel est l'avantage d'utiliser Timertask et Timer pour faire cela, plutôt que de créer un nouveau thread qui a une boucle infinie avec sleep ?

Extraits de code utilisant timertask-

TimerTask uploadCheckerTimerTask = new TimerTask(){

 public void run() {
  NewUploadServer.getInstance().checkAndUploadFiles();
 }
};

Timer uploadCheckerTimer = new Timer(true);
uploadCheckerTimer.scheduleAtFixedRate(uploadCheckerTimerTask, 0, 60 * 1000);

Extraits de code utilisant Thread et sleep-

Thread t = new Thread(){
 public void run() {
  while(true) {
   NewUploadServer.getInstance().checkAndUploadFiles();
   Thread.sleep(60 * 1000);
  }
 }
};
t.start();

Je n'ai vraiment pas à m'inquiéter de manquer certains cycles si l'exécution de la logique prend plus que le temps d'intervalle.

Veuillez commenter ce..

Mise à jour :
Récemment, j'ai découvert une autre différence entre l'utilisation de Timer et de Thread.sleep(). Supposons que l'heure actuelle du système est 11:00AM. Si, pour une raison quelconque, nous ramenons l'heure du système à 10h00, la minuterie cessera d'exécuter la tâche jusqu'à ce qu'elle atteigne 11h00, alors que la méthode Thread.sleep() continuera d'exécuter la tâche sans problème. Cela peut être un facteur de décision important pour choisir entre ces deux méthodes.

23 votes

Point d'ordre : Timer et TimerTask sont obsolètes, et ont été effectivement remplacés par ExecutorService, bien que votre remarque soit toujours valable.

0 votes

Merci pour le conseil, j'ai décidé d'utiliser ExecutorService :)

0 votes

Merci à tous pour les réponses, cela m'a permis de mieux comprendre !

68voto

Zed Points 27408

L'avantage de TimerTask est qu'il exprime bien mieux votre intention (c'est-à-dire la lisibilité du code), et qu'il dispose déjà de la fonction cancel().

Notez qu'il peut être rédigé sous une forme plus courte ainsi que votre propre exemple :

Timer uploadCheckerTimer = new Timer(true);
uploadCheckerTimer.scheduleAtFixedRate(
    new TimerTask() {
      public void run() { NewUploadServer.getInstance().checkAndUploadFiles(); }
    }, 0, 60 * 1000);

0 votes

Si le timer est utilisé pour Everyday, sur 2 heures spécifiques 9pm et 9am,... comment donner les valeurs ? sur le code ci-dessus ... @Zed ?

13voto

MartinStettner Points 14514

Timer/TimerTask prend également en compte le temps d'exécution de votre tâche, il sera donc un peu plus précis. Et il traite mieux les problèmes de multithreading (comme éviter les blocages, etc.). Et bien sûr, il est généralement préférable d'utiliser un code standard bien testé plutôt qu'une solution maison.

5voto

Qandeel Points 21

Je ne sais pas pourquoi mais un programme que j'écrivais utilisait des Timers et la taille de son tas augmentait constamment. Une fois que je l'ai changé en Thread/sleep, le problème a été résolu.

9 votes

La minuterie crée une file d'attente de tâches qui est continuellement mise à jour. Lorsque le temporisateur est terminé, il peut ne pas être immédiatement récupéré. Par conséquent, la création de plusieurs minuteurs ne fait qu'ajouter des objets supplémentaires au tas. Thread.sleep() ne fait que mettre le thread en pause, de sorte que la surcharge mémoire est extrêmement faible.

4voto

Boris Pavlović Points 22207

Il y a un argument crucial contre la gestion de cette tâche à l'aide de threads Java et de sleep méthode. Vous utilisez while(true) pour rester indéfiniment dans la boucle et hiberner le fil en le mettant en veille. Et si NewUploadServer.getInstance().checkAndUploadFiles(); prend des ressources synchronisées. Les autres threads ne pourront pas accéder à ces ressources, une famine peut se produire, ce qui peut ralentir l'ensemble de votre application. Ces types d'erreurs sont difficiles à diagnostiquer et il est préférable de les éviter.

L'autre approche déclenche l'exécution du code qui vous importe, à savoir NewUploadServer.getInstance().checkAndUploadFiles(); en appelant le run() de votre TimerTask tout en laissant les autres threads utiliser les ressources pendant ce temps.

16 votes

Je ne comprends pas cet argument. Les deux choix lancent la même méthode depuis un thread, les deux choix dorment dans un thread pendant qu'ils attendent l'exécution. Il n'y aura aucune différence de famine entre les deux choix.

4voto

Stack Popper Points 1

Si votre fil devient exceptionnel et est tué, c'est un problème. Mais TimerTask s'en chargera. Elle s'exécutera indépendamment de l'échec de l'exécution précédente.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X