1.ThreadLocal的數(shù)據(jù)結(jié)構(gòu),為什么要用static final 修飾ThreadLocal璃赡?
ThreadLocal結(jié)構(gòu)
某個(gè)threadlocal在全局是唯一的晓猛,并且存取的時(shí)候threadlocal只是作為Threadlocalmap下的一個(gè)key租幕,所以用static final修飾可以避免發(fā)生資源浪費(fèi)
1凉敲、每個(gè)Thread對(duì)象內(nèi)部都維護(hù)了一個(gè)ThreadLocalMap這樣一個(gè)ThreadLocal的Map,可以存放若干個(gè)ThreadLocal捅彻。
/* ThreadLocal values pertaining to this thread. This map is maintained
* by the ThreadLocal class. */
ThreadLocal.ThreadLocalMap threadLocals = null;
2组去、當(dāng)我們?cè)谡{(diào)用get()方法的時(shí)候,先獲取當(dāng)前線程沟饥,然后獲取到當(dāng)前線程的ThreadLocalMap對(duì)象添怔,如果非空湾戳,那么取出ThreadLocal的value贤旷,否則進(jìn)行初始化,初始化就是將initialValue的值set到ThreadLocal中砾脑。
public T get() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null)
return (T)e.value;
}
return setInitialValue();
}
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
3幼驶、當(dāng)我們調(diào)用set()方法的時(shí)候,很常規(guī)韧衣,就是將值設(shè)置進(jìn)ThreadLocal中盅藻。
4、總結(jié):當(dāng)我們調(diào)用get方法的時(shí)候畅铭,其實(shí)每個(gè)當(dāng)前線程中都有一個(gè)ThreadLocal氏淑。每次獲取或者設(shè)置都是對(duì)該ThreadLocal進(jìn)行的操作,是與其他線程分開的硕噩。
5假残、應(yīng)用場(chǎng)景:當(dāng)很多線程需要多次使用同一個(gè)對(duì)象,并且需要該對(duì)象具有相同初始化值的時(shí)候最適合使用ThreadLocal。
6辉懒、其實(shí)說再多也不如看一下源碼來得清晰阳惹。如果要看源碼,其中涉及到一個(gè)WeakReference和一個(gè)Map眶俩,這兩個(gè)地方需要了解下莹汤,這兩個(gè)東西分別是a.Java的弱引用,也就是GC的時(shí)候會(huì)銷毀該引用所包裹(引用)的對(duì)象颠印,這個(gè)threadLocal作為key可能被銷毀纲岭,但是只要我們定義成他的類不卸載,tl這個(gè)強(qiáng)引用就始終引用著這個(gè)ThreadLocal的线罕,永遠(yuǎn)不會(huì)被gc掉荒勇。b.和HashMap差不多。
事實(shí)上闻坚,從本質(zhì)來講沽翔,就是每個(gè)線程都維護(hù)了一個(gè)map,而這個(gè)map的key就是threadLocal窿凤,而值就是我們set的那個(gè)值仅偎,每次線程在get的時(shí)候,都從自己的變量中取值雳殊,既然從自己的變量中取值橘沥,那肯定就不存在線程安全問題,總體來講夯秃,ThreadLocal這個(gè)變量的狀態(tài)根本沒有發(fā)生變化座咆,他僅僅是充當(dāng)一個(gè)key的角色,另外提供給每一個(gè)線程一個(gè)初始值仓洼。如果允許的話介陶,我們自己就能實(shí)現(xiàn)一個(gè)這樣的功能,只不過恰好JDK就已經(jīng)幫我們做了這個(gè)事情色建。
2.重寫equals為什么要重寫hashCode()?
首先哺呜,從Object的源碼入手:
/**
* The {@code equals} method for class {@code Object} implements
* the most discriminating possible equivalence relation on objects;
* that is, for any non-null reference values {@code x} and
* {@code y}, this method returns {@code true} if and only
* if {@code x} and {@code y} refer to the same object
* ({@code x == y} has the value {@code true}).
* <p>
* Note that it is generally necessary to override the {@code hashCode}
* method whenever this method is overridden, so as to maintain the
* general contract for the {@code hashCode} method, which states
* that equal objects must have equal hash codes.
**/
public boolean equals(Object obj) {
//equals默認(rèn)比較的是句柄的內(nèi)存引用地址
return (this == obj);
}
/**
* hashcode方法是一個(gè)native方法,默認(rèn)返回引用地址
**/
public native int hashCode();
根據(jù)源碼注釋不難發(fā)現(xiàn)箕戳,equals必須遵從對(duì)等原則某残,x.equals(y) ==true 則
y.equals(x)==true,同時(shí)若復(fù)寫equals陵吸,則不需復(fù)寫hashcode玻墅。原因是:
若x.equals(y) ==true,則x.hashcode() == y.hashcode();
可以說這是一種原則上的規(guī)范壮虫;
一致性哈希
java線程狀態(tài)切換
java線程狀態(tài)切換