Article complet: ThreadLocal, partie 1, principes du stockage magique

01/04/2010

Permalink 00:00:01, Catégories: Récapitulatif Java, Java standard, Technique, 1000 mots   French (FR) , Delbecq David

[Java] ThreadLocal, partie 1, principes du stockage magique

Dans l'API java, on trouve une classe au comportement tout a fait particulier, ThreadLocal. Son principe: stocker des données dans le Thread courant afin de les récupérer plus tard, dans une autre méthode par exemple, sans avoir à les passer en argument à toute la chaine d'appel. Cette classe peut vous être d'un grand secours, mais elle doit être utilisée judicieusement et surtout en extrêmement précautionneusement!

[Suite:]

Historique

La classe ThreadLocal est apparue dans le JDK1.2, vers la fin 1998 (et oui, elle est méconnue, mais elle date!). Son utilisation principale, permettre à plusieurs threads de travailler simultanément sur une variable statique, tout en permettant à chaque Thread d'avoir sa propre instance de la variable ainsi qu'éventuellement, proposer un constructeur pour créer la valeur par défaut pour les threads qui n'en ont pas encore recu. Exemple, soit la classe suivante utilisée par 2 Threads:
public class Test { 
 //code java 5 
 public static ThreadLocal<Integer> x = new ThreadLocal<Integer>(); 
}
Thread 1Thread 2
valeur de xactionactionvaleur de x
-start-
1Test.x.set(1)-
1start-
2Test.x.set(Test.x.get()++)-
2Test.x.set(5)5
2Test.x.get() -> 25
2Test.x.set(Test.x.get()++)6
La première implémentation (jdk 1.2) de cette classe était assez simple. Une ThreadLocal se résumait à une Map<Thread,Object>. Et le get ressemblait grosso modo à ça:
private Map map=...;
   //......
   public Object get(){
     synchronized(map){
       if (!map.contains(Thread.currentThread()))
       map.put(Thread.currentThread(),initialValue());
       return map.get(Thread.currentThread());
     }
   }
Le problème principal de ce code: ses performances. Chaque appel à la méthode get() implicant un bloc synchronized, les performances étaient assez catastrophique quand les Thread étaient nombreux. Il devait être possible d'éviter ces blocs, puisque chaque thread utilisait des données différentes. Sun a donc revu sa copie, et a inversé la responsabilité du stockage. Au lieu d'avoir une classe ThreadLocal qui stocke les données pour chaque thread et dispatche la bonne valeur, en fonction du thread courant, on a maintenant le thread qui stocke les données, pour chaque instance des ThreadLocal de la jvm, et qui retourne la bonne valeur en fonction de l'instance de ThreadLocal utilisée. L'avantage est évident, comme les données sont a la base stockées dans la classe Thread, il n'est plus nécessaire d'avoir de bloc synchronized, et donc on a un gain non négligeable en performances. Mais il y a un fort contrecoup à cela. Comme les données sont stockées dans le thread, c'est une grande source de memory leak (tant que le thread vis, les données y restent). C'est ce dernier schéma de stockage qui est toujours en vigueur à ce jour (java 6).

1 2 Page suivante »

Social Bookmarking:

                                     

Commentaires:

Connectez-vous pour vous abonner à cet article:

Flux de commentaires pour cet article : Atom 1.0  RSS 2.0
Commentaire de: TheNOHDirector [Membre]
Je me permet de faire une remarque au sujet du ThreadLocal, autant cette classe peut servir, autant je déconseille son utilisation au possible!

En effet utiliser ce genre de chose, c'est comme si on utilisait des variables globales scopées dans une thread. Et les variables globales c'est très souvent mal!

http://fr.wikipedia.org/wiki/Variable_globale

Pour les les lecteurs anglophones il y a une entrée sur StackOverFlow, je conseille de lire les retours à la question : http://stackoverflow.com/questions/484635/are-global-variables-bad
Permalien 01/04/2010 @ 10:08
Commentaire de: TheNOHDirector [Membre]
Également sur StackOverFlow : http://stackoverflow.com/questions/817856/when-and-how-should-i-use-a-threadlocal-variable
Permalien 01/04/2010 @ 10:11
Commentaire de: Delbecq David [Membre]
Comme beaucoup de choses, ce qui compte c'est une utilisation correcte de celle-ci. Au bon endroit et en respectant certains principes, Parfois, il faut un moyen de passer des données en aval sans les passer en paramètre de méthode et soit on utilise ça, soit on réivente la roue en faisant le même à la main. Tout ça sera expliqué dans la partie deux à paraître ;)

Mais on est d'accord sur un point je pense, a moins d'avoir une très bonne raison de le faire, à ne pas utiliser.
Permalien 01/04/2010 @ 11:45
Commentaire de: benwit [Membre]
Deux petites remarques, ça serait plutôt :

1) On y vois la redéfinition de la méthode "initialValue()"

2) public static int getCurrentThreadId() {
return uniqueNum.get();
}
Permalien 01/04/2010 @ 13:20
Commentaire de: Delbecq David [Membre]
Merci benwit. Corrigé. Pour le 2, l'erreur viens de la javadoc de ThreadLocal, t'as plus qu'à leur adresser un bugreport :)
Permalien 01/04/2010 @ 14:01

Vous devez être identifié pour poster un commentaire.

Liste des blogs

Codes et autres, sauce java, parfum objet

Catégories


Rechercher

<  Avril 2011  >
Lun Mar Mer Jeu Ven Sam Dim
        1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30  

Syndiquez ce blog XML

Articles :

Commentaires :

 
 
 
 
Partenaires

Hébergement Web