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
- Java8 ThreadLocal类源码 详解
- ThreadLocal类详解与源码分析
- Java8源码-详解fail-fast
- 【Java8源码分析】线程-ThreadLocal的全面剖析
- ThreadLocal详解 (含源码)
- 源码浅析ThreadLocal类
- ThreadLocal类源码
- ThreadLocal类源码解析
- 【ThreadLocal】深入JDK源码之ThreadLocal类
- 【ThreadLocal】深入JDK源码之ThreadLocal类
- 详解ThreadLocal类
- ThreadLocal类详解
- ThreadLocal类详解
- java ThreadLocal源码详解及用法
- ThreadLocal源码
- ThreadLocal类详解及用途
- ThreadLocal类的使用详解
- Java8 观察者模式详解 jdk实现源码分析
- Win 7 下Excel2007如何用独立窗口打开
- 腾讯云centos7 服务器搭建(Java、MySQL、Tomcat环境配置)
- Android动态设置Shape
- 在aws的ec2上部署spark
- SpringMVC Mybatis的事务回滚问题
- Java8 ThreadLocal类源码 详解
- iOS开发之获取照片&&TZImagePickerController的使用
- spring InitializingBean接口
- 语音合成和识别接口
- MySql 时间比较:DATEDIFF函数与大于小于号
- OPENCV的2-10备注
- 安装selenium RC
- android studio编译运行各种踩坑解决方案
- 图片服务器架构