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的垃圾回收活动