ThreadLocal

1. The ThreadLocal object is created in the normal method or class which will be accesed by multi-thread.

pubic class Test{
ThreadLocal<Long> longLocal = new ThreadLocal<Long>();
ThreadLocal<String> stringLocal = new ThreadLocal<String>();

................
}

2.  The object of ThreadLocal<T> will store different object for different thread.

Different object of ThreadLocal<T> has different hashCode

private static int nextHashCode() {
        return nextHashCode.getAndAdd(HASH_INCREMENT);
    }

3. Set the value of threadlocal object

public void set(T value) {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
    }
ThreadLocalMap getMap(Thread t) {
        return t.threadLocals;
    }
void createMap(Thread t, T firstValue) {
        t.threadLocals = new ThreadLocalMap(this, firstValue);
    }

4. Every thread has its ThreadLocalMap

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

5. The ThreadLocalMap has an array of Entry, which has ThreadLocal object as key and is value.

static class Entry extends WeakReference<ThreadLocal> {
    /** The value associated with this ThreadLocal. */
    Object value;

    Entry(ThreadLocal k, Object v) {
        super(k);
        value = v;
    }
}
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
}

6. How to handle with confilct of Hash

/**
 * Increment i modulo len.
 */
private static int nextIndex(int i, int len) {
    return ((i + 1 < len) ? i + 1 : 0);
}

/**
 * Decrement i modulo len.
 */
private static int prevIndex(int i, int len) {
    return ((i - 1 >= 0) ? i - 1 : len - 1);
}

7. Keep in mind that the object ThreadLocal shall be removed after it is useless, it will lead to memory leak if no action on useless Threadlocal.

ThreadLocal<Session> threadLocal = new ThreadLocal<Session>();
try {
    threadLocal.set(new Session(1, "xxxx"));
} finally {
    threadLocal.remove();
}
public void remove() {
         ThreadLocalMap m = getMap(Thread.currentThread());
         if (m != null)
             m.remove(this);
     }
private void remove(ThreadLocal<?> key) {
            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)]) {
                if (e.get() == key) {
                    e.clear();
                    expungeStaleEntry(i);
                    return;
                }
            }
        }
 回收时间 使用场景
强引用    一直存活,除非GC Roots不可达 所有程序的场景,基本对象,自定义对象等。
软引用    内存不足时会被回收 一般用在对内存非常敏感的资源上,用作缓存的场景比较多,例如:网页缓存、图片缓存
弱引用    只能存活到下一次GC前 生命周期很短的对象,例如ThreadLocal中的Key。
虚引用    随时会被回收, 创建了可能很快就会被回收 业界暂无使用场景, 可能被JVM团队内部用来跟踪JVM的垃圾回收活动



原文地址:https://www.cnblogs.com/iiiDragon/p/9815951.html