TimerTask

Gestion des threads avec un compteur

Ce site ne sera plus alimenté de contenu après août 2014. Tous les nouveaux articles seront redigés pour www.waitingforcode.com

Napoléon a déjà traité la Chine d'un géant endormi. L'emperreur n'a pas prévu que quelques siècles plus tard, sa comparaison trouvera l'utilité dans le monde informatique. Et plus précisément, dans le monde des applications Java.

Le multi-threading de Java permet de faire tourner plusieurs tâches quasi simultanément. En plus de cela, on peut rajouter une synchronisation supplémentaire qui, par exemple, déclenchera l'exécution d'une tâche au bout d'un temps déterminé. C'est possible grâce aux java.util.TimerTask et java.util.Timer.

Regardons ceci en implémentant la phrase de Napoléon dans le code Java :

afficher le code

L'écran affichera :

China is woken up at Tue Oct 09 18:55:44 CEST 2012
China is woken up at Tue Oct 09 18:55:47 CEST 2012
China is woken up at Tue Oct 09 18:55:50 CEST 2012
China is woken up at Tue Oct 09 18:55:53 CEST 2012
China is woken up at Tue Oct 09 18:55:56 CEST 2012
China can't be woken up more than 5 times. We cancel Timer with timer.cancel()

Qu'est-ce qu'on remarque dans le code ? Au tout début on initialise la classe Timer qui se charge de faire tourner une tâche dans une intervalle temporaire. Elle possède une méthode schedule() qui peut prendre comme paramètre le début de l'exécution ainsi que le temps d'arrêt (en milisecondes) entre deux exécutions successives. Dans notre cas le Timer déclenchera la classe China d'ici 4 secondes et le fera tourner toutes les 3 secondes. On a également rajouté une vérification qui s'assure que China.run() soit exécutée au maximum 5 fois. Si la 6e exécution est invoquée, on fait appel à la méthode Timer.cancel() qui arrête la tâche.

Alternative à Timer et TimerTask

Une alternative aux deux classes décrites est java.util.concurrent.ScheduledExecutorService avec java.util.concurrent.ScheduledFuture. Constatons ceci sur notre exemple précédent :

afficher le code

Et le résultat affiché sur l'écran sera le même que dans le cas précédent :

China is woken up at Tue Oct 09 19:23:19 CEST 2012
China is woken up at Tue Oct 09 19:23:22 CEST 2012
China is woken up at Tue Oct 09 19:23:25 CEST 2012
China is woken up at Tue Oct 09 19:23:28 CEST 2012
China is woken up at Tue Oct 09 19:23:31 CEST 2012
China can't be woken up more than 5 times. We cancel ScheduledExecutorService with executor.shutdown()

Dans le code on voit qu'au début on crée l'instance du ScheduledExecutorService applicable à un Thread. Cette instance joue quasiement le même rôle que celle du Timer de l'exemple précédent. Sa méthode scheduleAtFixedRate() permet d'appeler un objet implémentant l'interface Runnable dans une intervale régulière, au bout d'un certain temps. En occurrence, l'intervale est égale à 3 secondes. Le début de l'exécution de la tâche est fixé à une seconde à partir de maintenant.

La différence entre Timer et Thread.sleep() en Java

L'atout principal du Timer ou ScheduledExecutorService est une meilleure lisibilité du code. Au lieu d'utiliser les méthodes peu explicites (Thread.sleep()), on emploie des fonctons destinées à faire ce qu'on veut. En outre, on n'a plus besoin d'implémenter la méthode d'arrêt car les deux classes évoquées ci-dessus en disposent (cancel() ou shutdown()).

Une différence peu flagrante au profit du Timer consiste au nombre de Threads créés. Chaque nouvelle instance de cette classe signifie la création d'un nouveau Thread tandis que la méthode sleep() s'applique au Thread current. Cette différence s'illustre donc en mémoire utilisée ainsi qu'un éventuel souci de synchronisation (accès concurrentiel à une ressource partagée par des tâches du Timer).

Bartosz KONIECZNY Concurrence

Une question ? Une remarque ?

*

*

Moi

Développeur d'applications Internet et journaliste passionné par l'adjectif français. Un aigle polonais orienté vers la progression, volant très haut et écoutant du zouk après les matches du foot français.

Vous appréciez mon travail ?

Pour contribuer au développement de ce site, ou pour remercier pour des articles rédigés, vous pouvez faire un don.

Un conseil Symfony1

Comment passer une variable depuis l'action vers le layout ?

Pour ce faire on peut utiliser les slots en appelant dans notre fichier d'action la méthode setSlot() :

$this->getResponse()->setSlot("titre_du_slot", array("12345"));

On le récupère dans le layout par la méthode get_slot() :
get_slot("titre_du_slot") ;