国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學(xué)院 > 開發(fā)設(shè)計(jì) > 正文

ThreadLocal解析

2019-11-14 15:31:09
字體:
供稿:網(wǎng)友

java同一線程進(jìn)行多Java實(shí)例對象調(diào)用中,可以使用TheadLoca進(jìn)行的數(shù)據(jù)傳遞。傳遞的數(shù)據(jù)在每個(gè)線程內(nèi)部獨(dú)享。

1、使用ThreadLocal。

public static void main(String[] args) {        ThreadLocal<String> threadLocal = new ThreadLocal<String>();        ThreadLocal<Integer> threadInt = new ThreadLocal<Integer>();          System.out.PRintln(threadLocal.get() + "--" + threadInt.get());        threadLocal.set("first");        threadInt.set(1);        System.out.println(threadLocal.get() + "--" + threadInt.get());        threadLocal.set("second");        threadInt.set(2);                System.out.println(threadLocal.get() + "--" + threadInt.get());        System.out.println(threadLocal.get() + "--" + threadInt.get());    }

 

 2、ThreadLocal類:

初始化ThreadLoca類時(shí),構(gòu)造函數(shù)為空

 /**     * ThreadLocals rely on per-thread linear-probe hash maps attached     * to each thread (Thread.threadLocals and     * inheritableThreadLocals).  The ThreadLocal objects act as keys,     * searched via threadLocalHashCode.  This is a custom hash code     * (useful only within ThreadLocalMaps) that eliminates collisions     * in the common case where consecutively constructed ThreadLocals     * are used by the same threads, while remaining well-behaved in     * less common cases.     */    private final int threadLocalHashCode = nextHashCode();/**     * Creates a thread local variable.     */    public ThreadLocal() {    }

 

其中變量threadLocalHashCode為不可變的final類型,表明該ThreadLocal實(shí)例中的該屬性一直不能改變,該變量賦值語句為:

 /**     * The next hash code to be given out. Updated atomically. Starts at     * zero.     */    private static AtomicInteger nextHashCode =        new AtomicInteger();    /**     * The difference between successively generated hash codes - turns     * implicit sequential thread-local IDs into near-optimally spread     * multiplicative hash values for power-of-two-sized tables.     */    private static final int HASH_INCREMENT = 0x61c88647;    /**     * Returns the next hash code.     */    private static int nextHashCode() {        return nextHashCode.getAndAdd(HASH_INCREMENT);    }

 

使用了靜態(tài)的類AtomicInteger,提供一個(gè)原子性的相加操作,保證每個(gè)線程之間的調(diào)用不會沖突,靜態(tài)AtomicInteger保證每個(gè)ThreadLoca的初始化都不會得到相同的值。其中添加量為:0x61c88647(為什么是這個(gè)值?)。

ThreadLocal提供了可供調(diào)用的方法:

  public T get()

  public void set(T value)

  public void remove()

先看set方法:

/**     * Sets the current thread's copy of this thread-local variable     * to the specified value.  Most subclasses will have no need to     * override this method, relying solely on the {@link #initialValue}     * method to set the values of thread-locals.     *     * @param value the value to be stored in the current thread's copy of     *        this thread-local.     */    public void set(T value) {        Thread t = Thread.currentThread();        ThreadLocalMap map = getMap(t);        if (map != null)            map.set(this, value);        else            createMap(t, value);    }

 

使用當(dāng)前Thread當(dāng)做Key,獲取ThreadLocalMap。

/**     * Get the map associated with a ThreadLocal. Overridden in     * InheritableThreadLocal.     *     * @param  t the current thread     * @return the map     */    ThreadLocalMap getMap(Thread t) {        return t.threadLocals;    }

 

最終返回的是Thread中的變量,threadLocals。

 /* ThreadLocal values pertaining to this thread. This map is maintained     * by the ThreadLocal class. */    ThreadLocal.ThreadLocalMap threadLocals = null;

 

Thread類中的變量,threadLocals為每個(gè)線程私有的屬性。同一個(gè)線程中的每一個(gè)ThreadLocal調(diào)用getMap(Thread t),都會得到相同的值, ThreadLocalMap:

/**     * ThreadLocalMap is a customized hash map suitable only for     * maintaining thread local values. No Operations are exported     * outside of the ThreadLocal class. The class is package private to     * allow declaration of fields in class Thread.  To help deal with     * very large and long-lived usages, the hash table entries use     * WeakReferences for keys. However, since reference queues are not     * used, stale entries are guaranteed to be removed only when     * the table starts running out of space.     */    static class ThreadLocalMap { /**         * The initial capacity -- MUST be a power of two.         */        private static final int INITIAL_CAPACITY = 16;        /**         * The table, resized as necessary.         * table.length MUST always be a power of two.         */        private Entry[] table;        /**         * The number of entries in the table.         */        private int size = 0;        /**         * The next size value at which to resize.         */        private int threshold; // Default to 0

 

ThreadLocalMap看名稱以為Map的子類,其實(shí)為一個(gè)普通類,內(nèi)部有一個(gè)數(shù)組  Entry[] table;

在ThreadLocal中的Set方法中,若Thread對象中的threadLocals為null( Thread對象中該屬性默認(rèn)為null),則調(diào)用createMap方法:

 /**     * Create the map associated with a ThreadLocal. Overridden in     * InheritableThreadLocal.     *     * @param t the current thread     * @param firstValue value for the initial entry of the map     * @param map the map to store.     */    void createMap(Thread t, T firstValue) {        t.threadLocals = new ThreadLocalMap(this, firstValue);    }

 

new 出一個(gè)ThreadLocalMap對象,賦值給Thread的threadLocals屬性,看構(gòu)造方法:

/**         * Construct a new map initially containing (firstKey, firstValue).         * ThreadLocalMaps are constructed lazily, so we only create         * one when we have at least one entry to put in it.         */        ThreadLocalMap(ThreadLocal firstKey, Object firstValue) {            table = new Entry[INITIAL_CAPACITY];            int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1);            table[i] = new Entry(firstKey, firstValue);            size = 1;            setThreshold(INITIAL_CAPACITY);        }

 

構(gòu)造時(shí)需要傳入兩個(gè)參數(shù), ThreadLocal與 Object作為key-value,  table數(shù)組初始化為16個(gè), threadLocalHashCode為傳入的ThreadLocal前面講過的不變值的屬性, 該值與15進(jìn)行與的操作,得到ThreadLocal對應(yīng)數(shù)組的index,同時(shí)設(shè)定該數(shù)組中index為new Entry對象。

/**         * The entries in this hash map extend WeakReference, using         * its main ref field as the key (which is always a         * ThreadLocal object).  Note that null keys (i.e. entry.get()         * == null) mean that the key is no longer referenced, so the         * entry can be expunged from table.  Such entries are referred to         * as "stale entries" in the code that follows.         */        static class Entry extends WeakReference<ThreadLocal> {            /** The value associated with this ThreadLocal. */            Object value;            Entry(ThreadLocal k, Object v) {                super(k);                value = v;            }        }

 Entry繼承了WeakReference, 使用一個(gè)ThreadLocal 的Weak引用,關(guān)于Java中的4種引用:

a.強(qiáng)引用(strong reference): Object obj = new Object(); obj就為一個(gè)強(qiáng)引用,obj=null后, 該對象可能會被JVM回收

b.軟引用(SoftReference): 

  SoftReference<Object> softref = new SoftReference<Object>(obj);  

  obj = null;

  在內(nèi)存不夠用的時(shí)候,才會回收軟引用的對象。

c.弱引用(WeakReference): 

  WeakReference<Object> weakRef = new WeakReference<Object>(obj);
  obj = null;

  該new出來的對象沒有強(qiáng)引用連接時(shí),下一次GC時(shí),就會回收該對象。

d.虛引用(PhantomReference),它保存ReferenceQueue中的軌跡

引自:http://m.survivalescaperooms.com/mengdd/p/3298852.html

此處使用弱引用,表明該ThreadLocal的Key轉(zhuǎn)換成弱引用的對象。此處使用弱引用的好處不影響該:ThreadLocal k 的生命周期,若程序運(yùn)行后,該ThreadLocal k連接的對象沒有強(qiáng)引用后,該Entry中的Key很快會被回收掉,變?yōu)閚ull,這樣的話 (private Entry[] table;)中的該index的位置就可以被再次使用了。

其中 setThreshold(),設(shè)定數(shù)組的閥值為  len * 2 / 3,  初始化時(shí)為10.

ThreadLocalMap中的set方法:

/**         * Set the value associated with key.         *         * @param key the thread local object         * @param value the value to be set         */        private void set(ThreadLocal key, Object value) {            // We don't use a fast path as with get() because it is at            // least as common to use set() to create new entries as            // it is to replace existing ones, in which case, a fast            // path would fail more often than not.            Entry[] tab = table;            int len = tab.length;            int i = key.threadLocalHashCode & (len-1);            for (Entry e = tab[i];                 e != null;                 e = tab[i = nextIndex(i, len)]) {                ThreadLocal k = e.get();                if (k == key) {                    e.value = value;                    return;                }                if (k == null) {                    replaceStaleEntry(key, value, i);                    return;                }            }            tab[i] = new Entry(key, value);            int sz = ++size;            if (!cleanSomeSlots(i, sz) && sz >= threshold)                rehash();        }

 

從key.threadLocalHashCode計(jì)算得到的第i個(gè)元素

若不為null,開始向后遍歷:

  若Entry中的k為Key,并且value也相等,則不做操作,返回。

  若Entry中的key為null,表明該Entry可以進(jìn)行下一步操作(replaceStaleEntry方法),可能是替換該Entry,也可能是查其它....

若為null,

  new Entry,賦值到數(shù)組中,

rehash方法中,判斷是否擴(kuò)容數(shù)據(jù), *2

 

get方法首先從ThreadLocalMap中查找,

/**         * Get the entry associated with key.  This method         * itself handles only the fast path: a direct hit of existing         * key. It otherwise relays to getEntryAfterMiss.  This is         * designed to maximize performance for direct hits, in part         * by making this method readily inlinable.         *         * @param  key the thread local object         * @return the entry associated with key, or null if no such         */        private Entry getEntry(ThreadLocal key) {            int i = key.threadLocalHashCode & (table.length - 1);            Entry e = table[i];            if (e != null && e.get() == key)                return e;            else                return getEntryAfterMiss(key, i, e);        }

 

若數(shù)組中的第i個(gè)不符合,則調(diào)用getEntryAfterMiss,向后遍歷。

 

 

參考:

http://m.survivalescaperooms.com/digdeep/p/4510875.html

http://wangxinchun.VEvb.com/blog/1884228

 


發(fā)表評論 共有條評論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 朝阳县| 昆山市| 江油市| 富民县| 夏津县| 岚皋县| 澄城县| 玉屏| 许昌县| 内黄县| 保亭| 耒阳市| 岑溪市| 双流县| 常德市| 抚宁县| 县级市| 绥滨县| 杨浦区| 云梦县| 长白| 海门市| 淄博市| 和田市| 元阳县| 巴青县| 麻江县| 临泉县| 灵台县| 罗田县| 广宗县| 衢州市| 崇仁县| 凤山县| 东乌珠穆沁旗| 巨鹿县| 平塘县| 库伦旗| 虞城县| 新丰县| 什邡市|