国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

ThreadLocal源碼

objc94 / 2583人閱讀

摘要:計(jì)算哈希后確定的槽內(nèi)是沒(méi)有表示沒(méi)有哈希沖突,此時(shí)一個(gè)放入槽內(nèi)。下一個(gè)位置繼續(xù)找如果循環(huán)結(jié)束了,表示哈希位往后尋找的都不是當(dāng)前的,返回。新的位置上有表示哈希沖突,則繼續(xù)向后尋找。

Thread和ThreadLocal的關(guān)系

初始化ThreadLocalMap和弱引用Entry
set方法與哈希沖突
清理槽
get方法也會(huì)清理槽
擴(kuò)容
手動(dòng)清理的重要性

Thread和ThreadLocal的關(guān)系

每個(gè)Thread中都持有一個(gè)ThreadLocalMap的實(shí)例,ThreadLocalMap是ThreadLocal的內(nèi)部類。當(dāng)Thread中沒(méi)有ThreadLocalMap則需要先實(shí)例化ThreadLocalMap.

public class Thread implements Runnable {    ThreadLocal.ThreadLocalMap threadLocals = null;//該對(duì)象是ThreadLocal中的內(nèi)部類ThreadLocalMap}public class ThreadLocal {    //計(jì)算出來(lái)的hash值用它來(lái)確定Entry存放到哪個(gè)哈希槽    private final int threadLocalHashCode = nextHashCode();    //這是個(gè)固定值    private static final int HASH_INCREMENT = 0x61c88647;    //這個(gè)默認(rèn)值是0,但new ThreadLocal后斷點(diǎn)看到的值不是0,這是因?yàn)檫@是一個(gè)靜態(tài)成員,在我們自己創(chuàng)建ThreadLocal前,main方法會(huì)先加載ThreadLocal給這個(gè)賦值了。    private static AtomicInteger nextHashCode = new AtomicInteger();    //每次調(diào)用該方法都會(huì)在原有的nextHashCode值上加上0x61c88647    private static int nextHashCode() {        return nextHashCode.getAndAdd(HASH_INCREMENT);    }        //設(shè)置值    public void set(T value) {        Thread t = Thread.currentThread();//獲取當(dāng)前線程。        ThreadLocalMap map = getMap(t);//獲取當(dāng)前線程的成員變量ThreadLocal.ThreadLocalMap threadLocals         if (map != null)            map.set(this, value);//如果當(dāng)前線程中的ThreadLocalMap已經(jīng)實(shí)例化則set        else            createMap(t, value);//如果當(dāng)前線程中的ThreadLocalMap沒(méi)有實(shí)例化則實(shí)例化。    }        //在這走實(shí)例化ThreadLocalMap    void createMap(Thread t, T firstValue) {        t.threadLocals = new ThreadLocalMap(this, firstValue);    }}

初始化ThreadLocalMap和弱引用Entry

ThreadLocalMap里最重要的屬性是Entry[],這個(gè)數(shù)組的初始長(zhǎng)度是16,擴(kuò)容閾值是size*2/3,Entry是ThreadLocalMap的內(nèi)部類,Entry繼承了弱引用。Entry里的key是ThreadLocal,value是設(shè)置的值。如果ThreadLocal棧引用結(jié)束了,在發(fā)生GC時(shí)雖然Entry還持有ThreadLocal的引用,這個(gè)ThreadLocal也會(huì)被垃圾回收,所以ThreadLocalMap常常伴隨著擴(kuò)容,清理操作。

static class ThreadLocalMap {    //繼承WeakReference很重要,WeakReferences是弱引用,在每次GC后都會(huì)回收弱引用對(duì)象里的引用值(若通過(guò)可達(dá)性分析查到引用值沒(méi)有其他可達(dá)的Root,則會(huì)回收)    //這個(gè)Entry就構(gòu)成了唯一的key,也就是ThreadLocal。value是ThreadLocal.set(parameter)的參數(shù)    static class Entry extends WeakReference> {            Object value;            Entry(ThreadLocal k, Object v) {                super(k);//最終傳遞給了Reference中的referent                value = v;            }    }        //ThreadLocalMap中的容器,一個(gè)線程持有一個(gè)ThreadLocalMap就相當(dāng)于持有了一個(gè)Entry數(shù)組    private Entry[] table;        //數(shù)組的初始容量    private static final int INITIAL_CAPACITY = 16;        ThreadLocalMap(ThreadLocal firstKey, Object firstValue) {            table = new Entry[INITIAL_CAPACITY];//實(shí)例化數(shù)組            int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1);//確定數(shù)組的位置            //初始化ThreadLocalMap不會(huì)出現(xiàn)hash沖突。            table[i] = new Entry(firstKey, firstValue);            //已有元素++            size = 1;            //計(jì)算擴(kuò)容閾值            setThreshold(INITIAL_CAPACITY);    }        private void setThreshold(int len) {            //初始化的容量第一次擴(kuò)容的閾值是10,也就是說(shuō)在數(shù)組的size是10的情況下就會(huì)觸發(fā)擴(kuò)容。            threshold = len * 2 / 3;    }  }
}

set方法與哈希沖突

ThreadLocal的set方法是使用ThreadLocalMap的set方法。他分為四種情況。1 計(jì)算哈希后確定的槽內(nèi)是null沒(méi)有Entry表示沒(méi)有哈希沖突,此時(shí)new一個(gè)Entry放入槽內(nèi)。 2 計(jì)算哈希后確定的槽內(nèi)有Entry但是槽內(nèi)的Entry的key和當(dāng)前的ThreadLocal相同則直接替換value。

3 計(jì)算哈希后確定的槽內(nèi)有Entry但是key和當(dāng)前ThreadLocal并不是同一個(gè),則表示哈希沖突,此時(shí)順著數(shù)組往右尋找,直到碰到有Entry但是沒(méi)有key的槽,這表示這個(gè)槽內(nèi)曾經(jīng)有過(guò)ThreadLocal但是被GC掉了,此時(shí)這個(gè)槽是個(gè)廢槽,可以替換掉Entry。 4 哈希沖突后向右

并沒(méi)有找到被GC的槽,此時(shí)只能是找到距離最近的一個(gè)槽內(nèi)沒(méi)有Entry的,創(chuàng)建一個(gè)Entry存入。

static class ThreadLocalMap {  //順著當(dāng)前下標(biāo)往后查詢。如果查詢到了數(shù)組末尾則返回0號(hào)下標(biāo)    private static int nextIndex(int i, int len) {            return ((i + 1 < len) ? i + 1 : 0);    }        //順著當(dāng)前下標(biāo)往前查詢。如果已經(jīng)是0則返回?cái)?shù)組末尾下標(biāo)    private static int prevIndex(int i, int len) {            return ((i - 1 >= 0) ? i - 1 : len - 1);    }        private void set(ThreadLocal key, Object value) {            //拿到數(shù)組            Entry[] tab = table;            //數(shù)組長(zhǎng)度            int len = tab.length;            //hash&length-1 效果類似hash%length            int i = key.threadLocalHashCode & (len-1);            //在這就要處理hash沖突了。如果hash值不沖突,那么算出來(lái)的index位置的Entry肯定是null.那么不會(huì)進(jìn)入循環(huán)。            //如果進(jìn)入了循環(huán),有沒(méi)有可能兩個(gè)if都不滿足,有可能。這表示hash值沖突了,但是不是同一個(gè)ThreadLocal,并且hash值相同的槽內(nèi)的ThreadLocal沒(méi)有被GC。            //那么只能是一直找到Entry是null的位置,然后跳出循環(huán)。            for (Entry e = tab[i];e != null;e = tab[i = nextIndex(i, len)]) {                ThreadLocal k = e.get();                //如果是第一次循環(huán)到這里進(jìn)去了,表示是同一個(gè)ThreadLocal多次設(shè)置值。則直接替換值。情況2                if (k == key) {                    e.value = value;                    return;                }                //如果ThreadLocal為null則表示發(fā)生了GC把弱引用ThreadLocal清理了。                //需要將當(dāng)前set的key和value放入這個(gè)廢掉的槽內(nèi),并且看看有沒(méi)有需要清理的槽。情況3                if (k == null) {                    replaceStaleEntry(key, value, i);                    return;                }            }            //沒(méi)有進(jìn)入循環(huán),或者從循環(huán)跳出了。如果沒(méi)有進(jìn)入循環(huán)則i就是hash&length-1的位置表示當(dāng)前算出來(lái)的hash值沒(méi)有沖突,也是第一次使用。情況1            //如果是循環(huán)跳出來(lái)的,則這個(gè)i就是hash&length-1.算出來(lái)的位置向后移動(dòng)循環(huán)次數(shù)的位置。表示hash沖突了,并且沖突后的槽往后也都沒(méi)有被GC            //只能是往后順延找別的可用槽。總之會(huì)找到一個(gè)在數(shù)組內(nèi)Entry為空的位置。創(chuàng)建Entry放進(jìn)數(shù)組。情況4            tab[i] = new Entry(key, value);            //已有元素++            int sz = ++size;
       //如果沒(méi)有清理槽,并且當(dāng)前長(zhǎng)度已經(jīng)大于等于了閾值則擴(kuò)容
if (!cleanSomeSlots(i, sz) && sz >= threshold) rehash(); } //走到這個(gè)方法表示通過(guò)hash&length-1的位置上的Entry中的key是null或者是哈希沖突后,往數(shù)組后查詢發(fā)現(xiàn)有Entry中的key是null private void replaceStaleEntry(ThreadLocal key, Object value,int staleSlot) { //數(shù)組 Entry[] tab = table; //數(shù)組長(zhǎng)度 int len = tab.length; Entry e; //Entry為null的哈希槽 int slotToExpunge = staleSlot; //從Entry為null的哈希槽位置向前找,一直找到Entry為null停止 for (int i = prevIndex(staleSlot, len);(e = tab[i]) != null;i = prevIndex(i, len)){ //在向前尋找的過(guò)程中標(biāo)記Entry中key為null的下標(biāo) if (e.get() == null) slotToExpunge = i; } //從Entry為null的哈希槽位置向后找,一直找到Entry為null停止 for (int i = nextIndex(staleSlot, len);(e = tab[i]) != null;i = nextIndex(i, len)) { //循環(huán)中的Entry中的key ThreadLocal k = e.get(); if (k == key) { //如果key相同則替換value e.value = value; //將Entry中ThreadLocal為null的賦值給當(dāng)前槽中 tab[i] = tab[staleSlot]; //在將Entry賦值給原來(lái)ThreadLocal為null的槽中。 //這兩行操作相當(dāng)于把槽里的內(nèi)容互換了,達(dá)到的效果是前邊的槽中的Entry有key,循環(huán)中的也就是后邊的沒(méi)有key tab[staleSlot] = e; //如果列表向左查詢沒(méi)有發(fā)現(xiàn)Entry中key有null的。則將當(dāng)前循環(huán)中的槽的位置賦值。 //因?yàn)樯蟽刹讲僮饕呀?jīng)把當(dāng)前槽變成了key為null的槽,所以此處記錄的位置就是key是null的位置 //如果向左查詢有Entry里是null值那就表示這個(gè)區(qū)間內(nèi)還有更左邊有key是null的 if (slotToExpunge == staleSlot){ slotToExpunge = i; } //清理槽 cleanSomeSlots(expungeStaleEntry(slotToExpunge), len); return; } //當(dāng)前循環(huán)中的槽也是被GC過(guò)的。并且向左查詢沒(méi)有發(fā)現(xiàn)Entry為null的,就記錄當(dāng)前槽的位置。 if (k == null && slotToExpunge == staleSlot){ slotToExpunge = i; } } //出循環(huán)只有一種情況,key為null的Entry下標(biāo)往后尋找沒(méi)有發(fā)現(xiàn)與當(dāng)前ThreadLocal相同的key。 //此時(shí)需要將原來(lái)Entry的value職位null。此操作用來(lái)釋放內(nèi)存。 tab[staleSlot].value = null; //創(chuàng)建一個(gè)新的Entry其中key是當(dāng)前ThreadLocal,value是set的參數(shù)。將它放到被GC的位置。 tab[staleSlot] = new Entry(key, value); //如果向左查詢有Entry中key是null的slotToExpunge就是在左邊確定的 //如果向左查詢沒(méi)有Entry中key是null的,而向右查詢有Entry中key是null的slotToExpunge就是右邊確定的。 //如果兩邊都沒(méi)有的情況表示當(dāng)前區(qū)間內(nèi)只有staleSlot一個(gè)為Entry是null的而這種情況下直接重新覆蓋了Entry。不需要清理。條件不成立。 if (slotToExpunge != staleSlot){ cleanSomeSlots(expungeStaleEntry(slotToExpunge), len); } } }

清理槽

expungeStaleEntry方法就是將廢槽清空,然后將哈希沖突的槽重新分配位置,因?yàn)楣_突后是從哈希位向后移動(dòng)尋找Entry是null的槽放入的,此后這些沖突的槽可能有被清理的,所以重新分配位置,方法的返回值是Entry為null的位置,cleanSomeSlots方法從這個(gè)位置

繼續(xù)尋找有沒(méi)有廢槽,如果有就清理。

static class ThreadLocalMap {      //接收的參數(shù)是槽里沒(méi)有Entry的槽和當(dāng)前數(shù)組的長(zhǎng)度    private boolean cleanSomeSlots(int i, int n) {            boolean removed = false;            Entry[] tab = table;            int len = tab.length;            do {                //找到下一個(gè)槽的位置                i = nextIndex(i, len);                //獲取槽內(nèi)的Entry                Entry e = tab[i];                //如果槽內(nèi)有Entry,并且Entry的key是null,表示這是個(gè)廢槽。                if (e != null && e.get() == null) {                    n = len;                    //有廢槽肯定要清理的。                    removed = true;                    //方法返回下一個(gè)槽內(nèi)沒(méi)有Entry的槽下標(biāo)                    i = expungeStaleEntry(i);                }            } while ( (n >>>= 1) != 0);//這個(gè)操作相當(dāng)于折半除2的操作。10,5,2,0,            return removed;    }        //接收的參數(shù)是槽下標(biāo)內(nèi)有Entry,但是Entry的key被GC了。    private int expungeStaleEntry(int staleSlot) {            Entry[] tab = table;            int len = tab.length;            //將槽清空            tab[staleSlot].value = null;            tab[staleSlot] = null;            //Entry[]--            size--;            Entry e;            int i;            //循環(huán)的開始是廢槽的下一個(gè),終止條件是下一個(gè)槽有Entry            for (i = nextIndex(staleSlot, len);(e = tab[i]) != null;i = nextIndex(i, len)) {                //拿到槽內(nèi)的ThreadLocal                ThreadLocal k = e.get();                //如果槽內(nèi)的key也是null則表示這也是個(gè)廢槽,則也需要做清空操作。                if (k == null) {                    e.value = null;                    tab[i] = null;                    size--;                } else {                    //如果槽內(nèi)有的Entry有key,則通過(guò)hash值算出槽的位置。                    int h = k.threadLocalHashCode & (len - 1);                    //如果算出的槽位置不是當(dāng)前的位置則表示這個(gè)key曾經(jīng)哈希沖突了,所以位置并不是哈希位。                    if (h != i) {                        //將這個(gè)槽清空                        tab[i] = null;                        //從計(jì)算的哈希位開始循環(huán),找到Entry為null的槽,將剛剛清空槽里的Entry重新安置。                        while (tab[h] != null){                            h = nextIndex(h, len);                        }                        //這一步的操作的意義在于,如果循環(huán)中有if條件滿足的,這代表當(dāng)前i這個(gè)位置之前有可用的槽,那就從哈希位開始往后找,找到空槽,重新安置這個(gè)Entry。                        tab[h] = e;                    }                }            }            return i;//入?yún)taleSlot是一個(gè)廢槽,返回的i則是一個(gè)Entry為null的槽。    }      }

get方法也會(huì)清理槽

get方法通過(guò)當(dāng)前ThreadLocal獲取Entry[]中對(duì)應(yīng)的Entry,如果ThreadLocalMap未實(shí)例化則實(shí)例化并返回null,通過(guò)哈希位找到了就返回,哈希位上的不是當(dāng)前ThreadLocal則表示哈希沖突,繼續(xù)在數(shù)組后尋找,如果途中發(fā)現(xiàn)有廢槽則清理,如果最終沒(méi)有找到則返回null。

public class ThreadLocal {       public T get() {        //獲取當(dāng)前線程        Thread t = Thread.currentThread();        //獲取線程內(nèi)的ThreadLocalMap        ThreadLocalMap map = getMap(t);        //如果ThreadLocalMap已經(jīng)實(shí)例化        if (map != null) {            //通過(guò)ThreadLocal這個(gè)key到數(shù)組中找到Entry,是有可能找不到返回null的            ThreadLocalMap.Entry e = map.getEntry(this);            //如果找到了,返回Entry中的value            if (e != null) {                @SuppressWarnings("unchecked")                T result = (T)e.value;                return result;            }        }        //走到這里兩種情況,1 ThreadLocalMap沒(méi)有實(shí)例化,則實(shí)例化 2 從Entry[]沒(méi)有找到對(duì)應(yīng)ThreadLocal的Entry        return setInitialValue();    }        //這個(gè)方法和set差不多,但是它可以返回null。    private T setInitialValue() {        //如果現(xiàn)在使用的就是ThreadLocal則一定返回null.        T value = initialValue();        Thread t = Thread.currentThread();        ThreadLocalMap map = getMap(t);        if (map != null)            map.set(this, value);        else            createMap(t, value);        return value;    }    //這個(gè)方法只能子類重寫,意味著可以給ThreadLocal賦默認(rèn)值。    protected T initialValue() {        return null;    }  }static class ThreadLocalMap {    static class ThreadLocalMap {    //通過(guò)ThreadLocal找Entry     private Entry getEntry(ThreadLocal key) {            //計(jì)算哈希位            int i = key.threadLocalHashCode & (table.length - 1);            //查看哈希位上的Entry            Entry e = table[i];            //如果Entry不是null或者Entry的key就是當(dāng)前的ThreadLocal則找到了返回Entry            if (e != null && e.get() == key){                return e;            }            else{                //如果從哈希位沒(méi)有找到Entry或者Entry中的key不是當(dāng)前ThreadLocal                return getEntryAfterMiss(key, i, e);            }    }    //接收的參數(shù)是當(dāng)前ThreadLocal,計(jì)算的哈希位,和這個(gè)哈希位上的Entry    private Entry getEntryAfterMiss(ThreadLocal key, int i, Entry e) {            Entry[] tab = table;            int len = tab.length;            //從哈希位上開始循環(huán)尋找            while (e != null) {                ThreadLocal k = e.get();                //如果找到了key相同的則返回                if (k == key){                    return e;                }                    //如果當(dāng)前槽內(nèi)的key是null則要被清理                if (k == null){                    expungeStaleEntry(i);                }else{                    //如果槽內(nèi)的key有值則繼續(xù)尋找。直到Entry位null停止。                    i = nextIndex(i, len);                }                //下一個(gè)位置繼續(xù)找                e = tab[i];            }            //如果循環(huán)結(jié)束了,表示哈希位往后尋找的key都不是當(dāng)前的ThreadLocal,返回null。            return null;    }    }

擴(kuò)容

當(dāng)數(shù)組內(nèi)的元素到達(dá)閾值后觸發(fā)擴(kuò)容,擴(kuò)容操作進(jìn)行前會(huì)遍歷數(shù)組進(jìn)行清理。如果清理后仍然達(dá)到閾值則二倍擴(kuò)容,循環(huán)擴(kuò)容前的數(shù)組,根據(jù)新數(shù)組的長(zhǎng)度重新計(jì)算哈希值,如果哈希槽內(nèi)沒(méi)有元素則放入,如果有則線性查詢可用槽放入。然后用新的數(shù)組替換老的數(shù)組。

?

static class ThreadLocalMap {   //擴(kuò)容         private void rehash() {            //清理一遍槽            expungeStaleEntries();            //大于閾值擴(kuò)容            if (size >= threshold - threshold / 4)                resize();        }                //全部清理        private void expungeStaleEntries() {            Entry[] tab = table;            int len = tab.length;            //遍歷數(shù)組清理            for (int j = 0; j < len; j++) {                Entry e = tab[j];                //發(fā)現(xiàn)廢槽就清理                if (e != null && e.get() == null){                    expungeStaleEntry(j);                }            }        }                private void resize() {            //擴(kuò)容前的數(shù)組            Entry[] oldTab = table;            //擴(kuò)容前數(shù)組的長(zhǎng)度            int oldLen = oldTab.length;            //二倍擴(kuò)容            int newLen = oldLen * 2;            //創(chuàng)建新的數(shù)組            Entry[] newTab = new Entry[newLen];            int count = 0;            //遍歷擴(kuò)容前的數(shù)組            for (int j = 0; j < oldLen; ++j) {                Entry e = oldTab[j];                //如果Entry不是null                if (e != null) {                    //獲取key                    ThreadLocal k = e.get();                    if (k == null) {                        //key是null清理                        e.value = null;                     } else {                        //根據(jù)哈希值算出來(lái)在新的數(shù)組中的位置。                        int h = k.threadLocalHashCode & (newLen - 1);                        //新的位置上有Entry表示哈希沖突,則繼續(xù)向后尋找。                        while (newTab[h] != null){                            h = nextIndex(h, newLen);                        }                        //找到一個(gè)Entry為null的位置存放Entry。                        newTab[h] = e;                        count++;                    }                }            }            //設(shè)置新的閾值            setThreshold(newLen);            //新數(shù)組內(nèi)元素的總個(gè)數(shù)            size = count;            //替換數(shù)組            table = newTab;        }    }

手動(dòng)清理的重要性

clear方法就是把ThreadLocal從Entry中刪除,然后刪除Entry。這樣Entry就沒(méi)有了引用會(huì)被GC。如果不使用clear,那么就算是ThreadLocal棧內(nèi)存釋放了,這個(gè)對(duì)象還是存在于Thread里的ThreadLocalMap里的Entry[]數(shù)組中,除非遇到GC否則永遠(yuǎn)存在。手動(dòng)清理的作用就在于不用等待GC自己把Entry清理。

public class ThreadLocal {  //通過(guò)ThreadLocalMap的remove方法釋放內(nèi)存    public void remove() {         ThreadLocalMap m = getMap(Thread.currentThread());         if (m != null)             m.remove(this);    }        ThreadLocalMap getMap(Thread t) {        return t.threadLocals;    }  }static class ThreadLocalMap {   //通過(guò)當(dāng)前ThreadLocal刪除    private void remove(ThreadLocal key) {            Entry[] tab = table;            int len = tab.length;            //計(jì)算哈希位            int i = key.threadLocalHashCode & (len-1);            //循環(huán)找匹配的key            for (Entry e = tab[i];e != null;e = tab[i = nextIndex(i, len)]) {                if (e.get() == key) {                    //調(diào)用Refereence的clear把key清空                    e.clear();                    //再次清理槽。                    expungeStaleEntry(i);                    return;                }            }    }}public abstract class Reference {  private T referent;//這個(gè)就是ThreadLocal對(duì)象    public void clear() {        this.referent = null;    }  }

?

?

?

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/124534.html

相關(guān)文章

  • 追蹤解析 ThreadLocal 源碼

    摘要:雖然類名中帶有字樣,但是實(shí)際上并不是接口的子類。是弱連接接口,這意味著如果僅有指向某一類,其任然有可能被回收掉。這里使用弱連接的意義,是為了防止業(yè)務(wù)代碼中置空對(duì)象,但是由于存在連接可達(dá),所以仍然無(wú)法回收掉該對(duì)象的情況發(fā)生。 零 前期準(zhǔn)備 0 FBI WARNING 文章異常啰嗦且繞彎。 1 版本 JDK 版本 : OpenJDK 11.0.1 IDE : idea 2018.3 2 T...

    wawor4827 評(píng)論0 收藏0
  • ThreadLocal源碼

    摘要:下來(lái)我們來(lái)看中的方法。從中可以看到真正保存的是在中,接著看看的源碼。數(shù)組的初始長(zhǎng)度為,最多可保存一旦超過(guò)就進(jìn)行擴(kuò)容增加一倍。而內(nèi)部利用數(shù)組來(lái)保存和值的,數(shù)組的索引就是的哈希值數(shù)組的長(zhǎng)度。 在Android-27中查看源碼: 在Looper源碼中,我們看到通過(guò)ThreadLocal的set方法來(lái)保存Looper,通過(guò)get方法來(lái)取出Looper。下來(lái)我們來(lái)看ThreadLocal中的se...

    岳光 評(píng)論0 收藏0
  • 深入理解Python中的ThreadLocal變量(中)

    摘要:在深入理解中的變量上中我們看到的引入,使得可以很方便地在多線程環(huán)境中使用局部變量。特別需要注意的是,基類的并不會(huì)屏蔽派生類中的創(chuàng)建。到此,整個(gè)源碼核心部分已經(jīng)理解的差不多了,只剩下用來(lái)執(zhí)行清除工作。 在 深入理解Python中的ThreadLocal變量(上) 中我們看到 ThreadLocal 的引入,使得可以很方便地在多線程環(huán)境中使用局部變量。如此美妙的功能到底是怎樣實(shí)現(xiàn)的?如果你...

    DataPipeline 評(píng)論0 收藏0
  • 您有一份ThreadLocal完全解析手冊(cè)

    摘要:返回索引位置的值。因?yàn)橐蕾囉陟o態(tài)成員變量的關(guān)系,所以它的肯定唯一獲取當(dāng)前線程。位置還沒(méi)有初始化第一次這個(gè),直接將放到的位置。在線程池模式下,生命周期伴隨著線程一直存在,可能出現(xiàn)內(nèi)存泄漏的情況,最好手動(dòng)調(diào)用方法。 本文原創(chuàng)地址,:jsbintask的博客(食用效果最佳),轉(zhuǎn)載請(qǐng)注明出處! 前言 ThreadLocal是jdk中一個(gè)非常重要的工具,它可以控制堆內(nèi)存中的對(duì)象只能被指定線程訪問(wèn),如...

    劉東 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<