Es gibt immer noch einen Unterschied zwischen ThreadLocal- und Thread -Element -Variablen. Die ThreadLocal -Klasse bietet Thread -Lokalvariablen. Diese lokale Variable unterscheidet sich von allgemeinen Mitgliedsvariablen. Wenn die ThreadLocal -Variable von mehreren Threads verwendet wird, kann jeder Thread nur eine Kopie der Variablen abrufen. Dies ist eine Beschreibung in der Java -API. Durch das Lesen des API -Quellcodes stellte ich fest, dass es sich nicht um eine Kopie handelt. Was ist das Konzept einer Kopie? Klone? Oder etwas anderes, zu vage.
Um genau zu sein, hat sich die Registrierung (Karte <Thread, t>) in der Variablen des Typs ThreadLocal geändert, aber die Variable des Typs ThreadLocal selbst ist in der Tat eins, und dies ist die Essenz!
Hier ist ein Beispiel:
1. Standardbeispiele
Die MyThreadlocal -Klasse ist definiert und ihr Objekt TLT wird erstellt und wird von vier Threads verwendet. Infolgedessen teilen sich die TLT -Variablen der vier Threads nicht. Die zweite besteht darin, ihre eigenen zu verwenden, was zeigt, dass die vier Threads eine Kopie von TLT (Klon) verwenden.
/*** Verwenden Sie ThreadLocal -Klasse*/öffentliche Klasse Mytheadlocal {// Definieren Sie eine ThreadLocal -Variable, um int oder Integer -Daten privates ThreadLocal <GanzEger> tl = neuer ThreadLocal <GanzEger> () {@Override Protected Integer initialValue () {return 0; }}; public Integer getNextnum () {// den Wert von TL und add 1 ab und aktualisiert den Wert von t1 tl.set (tl.get () + 1); return tl.get (); }} / *** Testen von Thread*/ public class testthread erweitert Thread {private mytheadlocal tlt = new myThreadLocal (); public testthread (mytheadlocal tlt) {this.tlt = tlt; } @Override public void run () {für (int i = 0; i <3; i ++) {System.out.println (Thread.currentThread (). GetName () + "/t" + tlt.getNextnum ()); }}} / *** ThreadLocal -Test*/ public class Test {public static void main (String [] args) {MyThreadLocal tlt = new MyThreadLocal (); Thread T1 = neuer TestThread (TLT); Thread T2 = neuer TestThread (TLT); Thread T3 = neuer TestThread (TLT); Thread T4 = neuer TestThread (TLT); t1.start (); t2.Start (); t3.Start (); t4.Start (); }}
Es ist ersichtlich, dass die drei Threads unabhängig nummeriert sind und sich nicht gegenseitig beeinflussen:
Thread-0 1 Thread-1 1 Thread-0 2 Thread-1 2 Thread-0 3 Thread-1 3 Thread-2 1 Thread-3 1 Thread-2 2 Thread-3 2 Thread-2 3 Thread-3 3 Vorgang mit dem Ausgangscode 0 fertiggestellt
Das TLT-Objekt ist eins, und das Unsinn TL-Objekt ist ebenfalls eins, da die Kombinationsbeziehung eins zu eins ist. Mit zunehmender Anzahl der Threads werden jedoch viele ganzzahlige Objekte erstellt. Es ist nur diese Ganzzahl und INT sind bereits üblich. Ich kann also nicht die Objekteigenschaften der Ganzzahl spüren.
2. Verwenden Sie ThreadLocal nicht
Wenn Sie ThreadLocal nicht verwenden, müssen Sie nur die MyThreadlocal -Klasse als:
/ *** Verwenden Sie ThreadLocal -Klasse*/ öffentliche Klasse mytheadlocal {private Integer t1 = 0; public Integer getNextnum () {return t1 = t1+1; } // Definieren Sie eine ThreadLocal -Variable, um int- oder Integer -Daten zu speichern // private ThreadLocal <Neger> tl = new ThreadLocal <GanzEger> () {// @Override // Protected Integer initialValue () {// return 0; //} //}; // // public Integer getNextnum () {// // den Wert von TL und add 1 und aktualisieren Sie den Wert von t1 // tl.set (tl.get () + 1); // tl.get () zurückgeben; //}}
Dann führen Sie den Test aus:
Thread-2 1 Thread-2 2 Thread-1 4 Thread-1 6 Thread-3 3 Thread-3 9 Thread-3 10 Thread-1 8 Thread-0 7 Thread-0 11 Thread-0 12 Thread-2 5 Vorgang mit dem Ausgangscode 0 fertiggestellt
Von hier aus können wir sehen, dass die vier Threads die TLT -Variable teilen und jeder Thread die Eigenschaften des TLT direkt verändert.
3.. ThreadLocal alleine realisieren
Paket com.lavasoft.test2; Import Java.util.Collections; import Java.util.hashMap; import Java.util.map; /*** Verwenden Sie ThreadLocal -Klasse*/public class mytheadlocal {// eine ThreadLocal -Variable definieren, um int oder integer data private com.lavasoft.Test2.ThreadLocal <Integer> tl = new Com.lavasoft.Test2. ThreadLocal <Integer> () {@override Protected Inteteger InitialValu () {) Return 0; }}; public Integer getNextnum () {// den Wert von TL und add 1 ab und aktualisiert den Wert von t1 tl.set (tl.get () + 1); return tl.get (); }} Klasse ThreadLocal <T> {private map <thread, t> map = collections.synchronizedMap (neuer Hashmap <Thread, t> ()); public threadLocal () {} protected t initialValue () {return null; } public t get () {thread t = thread.currentThread (); T obj = map.get (t); if (obj == null &&! map.containsKey (t)) {obj = initialValue (); map.put (t, obj); } return obj; } public void set (t value) {map.put (thread.currentThread (), value); } public void remove () {map.remove (thread.currentThread ()); }}
Führen Sie den Test aus:
Thread-0 1 Thread-0 2 Thread-0 3 Thread-2 1 Thread-2 2 Thread-3 1 Thread-2 3 Thread-3 2 Thread-1 1 Thread-3 3 Thread-1 2 Thread-1 3 Vorgang mit dem Ausgangscode 0 fertiggestellt
Überraschenderweise funktioniert diese Nachahmerversion von ThreadLocal auch gut und implementiert die Funktion von ThreadLocal in Java -API.
4. Siehe die Essenz durch Phänomene
Tatsächlich ist die TLT -Variable aus programmierter Sicht ohne Zweifel eins. Aber warum wirken sich die gedruckten Zahlen nicht aufeinander aus?
Liegt es an der Verwendung von Integer? -----NEIN.
Der Grund ist: Protected t initialValue () und get (), denn wenn jeder Thread aufruft, wird () erstellt, wenn er in der Karte nicht vorhanden ist. Wenn es aufgerufen wird, wird eine neue Variable mit Typ T erstellt. Jedes Mal, wenn sie neu erstellt werden, verwendet sie natürlich jeder sie ohne Auswirkungen aufeinander.
Um die Essenz klar zu sehen, ersetzen Sie Ganzzahl und schreiben Sie einige Klassen um:
Paket com.lavasoft.test2; Import Java.util.Collections; import Java.util.hashMap; import Java.util.map; /*** Verwenden Sie ThreadLocal -Klasse*/public class mytheadlocal {// eine ThreadLocal -Variable definieren, um int oder integer -Daten zu speichern // private ThreadLocal <Bean> tl = new ThreadLocal <Bean> () {private COM.Lavasoft.Test2. ThreadLocal <Bean> Tl = @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @@lavasoft.test2.Test2. initialValue () {return New Bean (); }}; @Override public String toString () {return "mytheadlocal {" + "tl =" + tl + '}'; } public bean getBean () {return tl.get (); }} Klasse ThreadLocal <T> {private map <thread, t> map = collections.synchronizedMap (neuer Hashmap <Thread, t> ()); public threadLocal () {} protected t initialValue () {return null; } public t get () {thread t = thread.currentThread (); T obj = map.get (t); if (obj == null &&! map.containsKey (t)) {obj = initialValue (); map.put (t, obj); } return obj; } public void set (t value) {map.put (thread.currentThread (), value); } public void remove () {map.remove (thread.currentThread ()); }} Paket com.lavasoft.test2; / ** * test bean */ public class bean {private string id = "0"; private String name = "Keine"; public bean () {} public bean (String -ID, String -Name) {this.id = id; this.name = name; } public String getId () {return id; } public void setID (String -ID) {this.id = id; } public String getName () {return name; } public void setName (String -Name) {this.name = name; } public String showInfo () {return "bean {" + "id = '" + id +'/'' + ", name = '" + name +'/'' + '}'; }} Paket com.lavasoft.test2; / *** Testen von Thread*/ public class testthread erweitert Thread {private mytheadlocal tlt = new myThreadLocal (); public testthread (mytheadlocal tlt) {this.tlt = tlt; } @Override public void run () {System.out.println (">>>:" + tlt); für (int i = 0; i <3; i ++) {System.out.println (thread.currentThread (). getName ()+"/t"+tlt.getBean ()+"/t"+tlt.getBean (). ShowInfo ()); }}}
Dann führen Sie den Test aus:
>>>>>>: mytheadlocal {Tl=com.lavasoft.test2.mythreadlocal$1@1de3f2d} >>>>>: mytheadlocal {Tl=com.lavasoft.test2.mythreadLocal1@1de3f2d} >>>>>>>>: mytheadlocal aw Bean {id = '0', name = 'none'} thread-2 com.lavasoft.test2.bean@fe64b9 bean {id = '0', name = 'none'} thread-3 com.lavasoft.test2.bean@186db54 bean { Bean{id='0', name='none'} Thread-2 com.lavasoft.test2.Bean@fe64b9 Bean{id='0', name='none'} Thread-2 com.lavasoft.test2.Bean@fe64b9 Bean{id='0', name='none'} Thread-0 com.lavasoft.test2.Bean@291aff Bean {id = '0', name = 'none'} thread-3 com.lavasoft.test2.bean@186db54 bean {id = '0', name = 'none'} thread-3 com.lavasoft.test2.bean@186db54 Bean {{{{0 ', name ='} thread '} thread'} thread '}'} thread-1 com. Bean {id = '0', name = 'none'} thread-0 com.lavasoft.test2.bean@291aff Bean {id = '0', name = 'none'} thread-0 com.lavasoft.test2.bean@291aff Bean {id = '0', name = '} thread-1.lavasoft.test2. Bean {id = '0', name = 'none'} Prozess mit dem Bezugscode 0 abgeschlossen
Aus den Druckergebnissen geht hervor, dass das TLT -Objekt von MyThreadLocal tatsächlich eins ist und das TL -Objekt von ThreadLocal im TLT -Objekt ebenfalls eins ist. Wenn T1T für jeden Thread verwendet wird, erstellt der Thread das Bean -Objekt und fügt es zur Verwendung zur ThreadLocal -Karte hinzu.
Mehrere Missverständnisse über ThreadLocal:
1. ThreadLocal ist eine Implementierung von Java -Threads
ThreadLocal hängt tatsächlich mit Java -Threads zusammen, aber es ist keine Implementierung von Java -Threads, sondern nur zur Aufrechterhaltung lokaler Variablen. Für jeden Thread bietet es eine eigene variable Version, hauptsächlich, um Thread -Konflikte zu vermeiden, und jeder Thread hält eine eigene Version. Seien Sie unabhängig voneinander, und die Änderung wirkt sich nicht gegenseitig aus.
2. ThreadLocal ist relativ zu jeder Sitzung
ThreadLocal richtet sich, wie der Name schon sagt, auf Threads. In der Java -Webprogrammierung hat jeder Benutzer eine eigene Sitzungskennung vom Anfang bis zum Ende der Sitzung. Aber ThreadLocal befindet sich nicht auf der Sitzungsschicht. ThreadLocal ist unabhängig von der Benutzersitzung. Es ist ein serverseitiges Verhalten. Immer wenn ein Server einen neuen Thread generiert, verwaltet er seinen eigenen ThreadLocal.
In Bezug auf dieses Missverständnis glaube ich persönlich, dass dies das Ergebnis des lokalen Tests des Entwicklers sein sollte, der auf einigen Anwendungsservern basiert. Wie wir alle wissen, verwalten allgemeine Anwendungsserver eine Reihe von Threadpools, dh für jeden Zugriff erzeugt ein neuer Thread nicht unbedingt. Stattdessen habe ich einen Thread -Cache -Pool. Für den Zugriff finden Sie zunächst die vorhandenen Threads aus dem Cache -Pool. Wenn sie alle verbraucht haben, wird ein neuer Thread erzeugt.
Da der Entwickler normalerweise der einzige ist, der sich selbst testet, ist die Serverbelastung sehr klein, was jedes Mal, wenn der Zugriff ist
3. ThreadLocal ist relativ zu jedem Thread. Jedes Mal, wenn der Benutzer zugreift, gibt es einen neuen ThreadLocal.
Theoretisch ist ThreadLocal in der Tat relativ zu jedem Thread. Jeder Thread hat seinen eigenen ThreadLocal. Wie oben erwähnt, führen allgemeine Anwendungsserver jedoch eine Reihe von Threadpools. Daher erhalten verschiedene Benutzer denselben Thread. Wenn Sie also die von der Headlokal basierende Überwachung durchführen, müssen Sie daher vorsichtig sein, um den Cache von Threadlokal-Variablen zu vermeiden, wodurch andere Threads auf die Thread-Variablen zugreifen können
4. Für jeden Benutzerzugriff kann ThreadLocal mehrmals verwendet werden.
Es kann gesagt werden, dass ThreadLocal ein zweischneidiges Schwert ist und bei Verwendung sehr gute Ergebnisse erzielen kann. Wenn ThreadLocal jedoch nicht gut verwendet wird, ist es die gleichen globalen Variablen. Der Code kann nicht wiederverwendet werden und kann nicht unabhängig getestet werden. Weil einige Klassen, die wiederverwendet werden könnten, jetzt auf die Threadlokal -Variable beruhen können. Wenn es keinen ThreadLocal gibt, werden diese Klassen nicht verfügbar. Ich persönlich denke, dass ThreadLocal gut verwendet wird und es wert ist, sich darauf zu beziehen
1. Speichern Sie den aktuellen Sitzungsbenutzer: Quake Want Jert
2. Speichern Sie einige Kontextvariablen, wie z. B. den ActionContext von Webwork
3. Store -Sitzungen wie Frühlings -Hibernate -Orm -Sitzungen