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 1 | | Thread 2 |
| valeur de x | action | action | valeur de x |
| - | start | | - |
| 1 | Test.x.set(1) | | - |
| 1 | | start | - |
| 2 | Test.x.set(Test.x.get()++) | | - |
| 2 | | Test.x.set(5) | 5 |
| 2 | Test.x.get() -> 2 | | 5 |
| 2 | | Test.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 »