代码改变世界

ThreadLocal 原理及用法简析

2015-04-23 14:31  zjxbr  阅读(197)  评论(0)    收藏  举报

1.Thread 类

ThreadLocal.ThreadLocalMap threadLocals = null;

 

 Thread 类持有 一个ThreadLocalMap对象,该对象是自定义类似map的数据结构

2.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.
     */

该类key 是 弱引用,在没有对象引用该key时,会垃圾回收(可能会被垃圾回收,当内存不足时候?不确定需要调查一下垃圾回收)

 

3.ThreadLocal类

该类通过获取Thread 的ThreadLocalMap属性来获得Map,该map是我们想要对线程存的值

 

/**
     * 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;
    }

 

get和set方法可以往里面设置值

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);
    }

 

个人理解是在线程中共享变量的方式。

但是并不可靠,因为是弱引用。

所以在用的时候一定要判断取出的值是否为空,如下: 

      private static final ThreadLocal<Integer> callId = new ThreadLocal<Integer>();

......

final
Integer id = callId.get(); if (id == null) { this.id = nextCallId(); } else { callId.set(null); this.id = id; }