Java8 ThreadLocal类源码 详解

来源:互联网 发布:可靠的韩国代购淘宝 编辑:程序博客网 时间:2024/05/19 13:43

JDK里有一个ThreadLocal这么一个类,其实起这个名字不是很贴近,这个类相当于给线程设置上了一个局部变量。使得,不会因为多线程访问同一个资源而产生多线程同步问题。

因为这个ThreadLocal类里面放的是每个线程都拥有一个副本,线程之间彼此不会互相影响。

现在这里笔者将会从源码的实现角度给大家讲述一下ThreadLocal实现的原理。

首先我们来看一下set()这个方法的实现。



所有的讲解笔者都将以注释的形式给出。

 public void set(T value) {     //拿到当前线程对象       Thread t = Thread.currentThread(); //拿到一个Map对象,好,那么问题来了?这个是一个什么样的map对象呢?? //其实这个ThreadLocalMap对象是ThreadLocal类内部自己实现的一个类似于HashMap这样一个类        ThreadLocalMap map = getMap(t);//如果map非空,则将当前的ThreadLocal对象和这个set()方法的参数put到这个Map里面去,//如果没有将其创建。        if (map != null)            map.set(this, value);        else            createMap(t, value);    }



我们可以看到ThreadLocal这个类里面确实定义了一个ThreadLocalMap类。里面的实现和HashMap的差不多,笔者就不点进去看了。




再一个我们点进去get()方法里面去看以下。


public T get() {//拿到当前的线程对象        Thread t = Thread.currentThread();//拿到ThreadLocalMap对象,到了这里我们进去getMap()方法里面去看一下         ThreadLocalMap map = getMap(t);        if (map != null) {            ThreadLocalMap.Entry e = map.getEntry(this);            if (e != null) {                @SuppressWarnings("unchecked")                T result = (T)e.value;                return result;            }        }        return setInitialValue();    }


相比,看到了前面的解释,  各位读者也很想进去看一看getMap的实现。

 ThreadLocalMap getMap(Thread t) {     //从这里可以看出 ThreadLocalMap对象是由当前的线程对象持有的,//但是维护的工作是由ThreadLocal这个类来完成的。       return t.threadLocals;    }




//createMap方法在当前线程对象内部持有的那个ThreadLocalMap对象为空,会调用之//从这里我们也可以看出是ThreadLocal这个类在维护这个关系void createMap(Thread t, T firstValue) {        t.threadLocals = new ThreadLocalMap(this, firstValue);    }
写到这里我们可以下一个结论。

ThreadLocal底层是使用一个自己实现的Map来存储用户set()进来的值。   那个map的键,即为当前的ThreadLocal对象。

有的朋友可能会问了。现在ThreadLocal只有一个对象。那么Map里的值还不是会被其他线程所共享。

其实这个不是的,笔者刚开始也是这么考虑的----------->这个Map里存储的应该是当前的Thread对象和值。而不应该是上面那种。

其实不是的。  因为那个ThreadLocal类自己实现的Map对象是每个线程对象内部自己持有一份。所以说,每个线程对象内的ThreadLocalMap对象是不一样的。所以,里面的数据是不会被其他线程所共享,都是自己用自己的。

这里笔者写了一个demo来证明每个线程持有的ThreadLocalMap对象是不同的。


package multiThread;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;import java.util.concurrent.CyclicBarrier;class MyThread implements Runnable{        private CyclicBarrier cyclicBarrier;        /**     * 第一个线程所持有的ThreadLocalMap对象     */    static Object object1 = null;        /**     * 第二个线程所持有的ThreadLocalMap对象     */    static Object object2 = null;        public MyThread(CyclicBarrier cyclicBarrier)    {        this.cyclicBarrier = cyclicBarrier;    }        @Override    public void run()    {        ThreadLocal threadLocal = new ThreadLocal();                Thread thread = Thread.currentThread();                Class<?> clazz = ThreadLocal.class;                Method createMap = null;                try        {            Method[] methods = clazz.getDeclaredMethods();                        Method createMapMethod = null;                /**             * 通过反射拿到createMap方法的Method对象             */            for(Method method : methods)            {                if("createMap".equals( method.getName() ))                {                    createMapMethod = method;                                    }            }                        System.out.println( createMapMethod );                                    if(createMapMethod != null)            {                createMapMethod.setAccessible( true );                createMapMethod.invoke( threadLocal, thread, "helloworld" );            }                /**             * 通过执行getMap()方法拿到那个LocalThreadMap对象             */            Method getMap = clazz.getDeclaredMethod( "getMap", Thread.class );                        getMap.setAccessible( true );                        System.out.println( getMap.invoke( threadLocal, thread ) );                        if("thread1".equals( Thread.currentThread().getName() ))            {                object1 = getMap.invoke( threadLocal, thread );            }            if("thread2".equals( Thread.currentThread().getName() ))            {                object2 = getMap.invoke( threadLocal, thread );            }                /**             * 等两个线程都先拿到那个ThreadLocalMap对象才开始执行CyclicBarrier构造方法里面的那个Runnable接口的匿名类里的run方法,             * 由最后一个完成的线程执行。             */            cyclicBarrier.await();        }        catch(Exception e)        {            e.printStackTrace();        }                    }}public class ThreadLocalTest{    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, InterruptedException, NoSuchMethodException, InstantiationException, InvocationTargetException    {        CyclicBarrier cyclicBarrier = new CyclicBarrier( 2, new Runnable()        {            @Override            public void run()            {                /**                 * 判断两个线程对象内所持有的ThreadLocalMap是否为同一对象                 */                System.out.println(MyThread.object1 == MyThread.object2);            }        } );            MyThread myThread = new MyThread( cyclicBarrier );                Thread thread1 = new Thread( myThread, "thread1" );        Thread thread2 = new Thread( myThread, "thread2" );        thread1.start();        thread2.start();            }}



0 0
原创粉丝点击