JAVA多线程----ThreadLocal

来源:互联网 发布:英雄联盟遇到网络问题 编辑:程序博客网 时间:2024/04/30 04:15
Thread类中相关代码如下:
    /* ThreadLocal values pertaining to this thread. This map is maintained     * by the ThreadLocal class. */    ThreadLocal.ThreadLocalMap threadLocals = null;

    这个实例变量,只有在exit()方法中,才被使用,将其赋值为null。


ThreadLocal类中相关代码如下

    /**     * Returns the value in the current thread's copy of this     * thread-local variable.  If the variable has no value for the     * current thread, it is first initialized to the value returned     * by an invocation of the {@link #initialValue} method.     *     * @return the current thread's value of this thread-local     */    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();    }    /**     * 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);    }    /**     * 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;    }    /**     * 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);    }    /**     * 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 {    .....}


       1.每个Thread实例中都存储各自ThreadLocal.ThreadLocalMap实例。所以各线程间不会共享资源
       2.线程中的ThreadLocalMap变量的值是在ThreadLocal实例进行get或者set操作时创建的
       3.ThreadLocal.ThreadLocalMap中,key是ThreadLocal实例,value就是需要存储的值

       至少完成了两个方面的数据的隔离:
       纵向----线程与线程之间访问各自的ThreadLocalMap实例
       横向----同一个线程中,ThreadLocalMap实例中,不同的ThreadLocal实例为key映射不同的value

       

在上面的代码中,ThreadLocalMap是ThreadLocal的嵌套类(这样其实我们完全可以将他们看做两个独立的类,只不过相互之间可以访问私有成员)。

      (1)在代码任何位置都可以获得当前的Thread实例;

      (2)Thread只是持有ThreadLocalMap实例,且不会对其做任何有用的操作;不会持有ThreadLocal实例

      (3)ThreadLocalMap的操作在ThreadLocal的方法中,所以需要有ThreadLocal的实例来完成,ThreadLocal实例可以获取当前执行线程的实例进而获取ThreadLocalMap实例,然后以自身为key进行存取操作

        所以要使用ThreadLocal,最关键的就是创建一个任何地方都可以访问到的ThreadLocal实例。这个实例需要在整个线程运行期间都可以获取得到特定的ThreadLocal实例,这样才能保证以该实例为key来保存的那个值可以在线程运行期间可以始终获取的到

       1.在我们的应用类中,添加一个ThreadLocal类型的静态实例变量,代码如下

public class ThreadTest{    public static void main(String args[])    {        Task2 t2 = new Task2();        for (int i = 0; i< 4;i ++)        {            Thread t = new Thread(t2);            t.start();        }    }}class Task1 implements Runnable{    private static ThreadLocal<Integer> countTL = new ThreadLocal<Integer>(){        protected synchronized Integer initialValue(){        return 10;}    };        public Integer get(){        return countTL.get();    }        public void set(Integer value){        countTL.set(value);    }    public void run()    {        set(0);        for (int i = 0;i < 10;i++)        {            set(get() + 1);            System.out.println(Thread.currentThread().getName() + "||" + get());        }    }}class Task2 implements Runnable{    private static int a = 0;    public void run()    {        for (int i = 0;i < 10;i++)        {            a = a + 1;            System.out.println(Thread.currentThread().getName() + "||" + a);        }    }}

原创粉丝点击