线程内部存储---TheadLocal从使用到源码分析
2017-07-10 09:48
417 查看
ThreadLocal是什么?
ThreadLocalThreadLocal是一个线程内部用于存储数据的类,通过它可以在指定的线程中存储数据,数据存储以后,只有在该线程中可以获取到存储的数据,对于其它线程来说无法获取到数据。个人认为是一个线程内部的存储机制。如何使用?
ThreadLocal<Boolean> threadLocal = new ThreadLocal<>();
这样就在一个线程创建了ThreadLocal这个对象,这个对象支持范性的,也就是说我们可以存储的自己想存的任意类型。
threadLocal.set(true);
这样我们就在当前所在线程,存储了true。
new Thread("Thread#1") { @Override public void run() { System.out.println(threadLocal.get()); }; }.start();
我们在一个分线程去打印这个刚才存储的值会发现是null,因为这是在两个线程操作的。如果在当前线程获取则为正确刚才存的值。
如果想移除这个数据也很简单:
threadLocal.remove();
这就是threadLocal的使用,其实很简单。 主要记得是区分线程的就ok。
内部源码是如何实现的呢?
这就是treadLocal中的所有方法了,其实我们最关心的就是set和get方法。
我们先看set:
public void set(T value) { Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) map.set(this, value); else createMap(t, value); }
这就是set方法,对就这么几行。
首先会通过Thread.currentThread();这个方法获取当前线程的Thread。然后通过getMap()获取 ThreadLocalMap对象。
ThreadLocalMap getMap(Thread t) { return t.threadLocals; }
getMap中也很简单,就是返回这个线程的threadLocals, 这个ThreadLocal就是 Thread中的一个变量ThreadLocal.ThreadLocalMap threadLocals = null;
其实还是ThreadLocal中的内部类ThreadLocalMap;这里一会在分析,先顺着思路往下走。
获取map之后会根据判断如果不是null就进行set,也就是存储,如果是null就会调用createMap()方法进行创建这个ThreadMap。接下来在看是如何set和createMap的。
创建其实很简单,直接就是new一个。
void createMap(Thread t, T firstValue) { t.threadLocals = new ThreadLocalMap(this, firstValue); }
set方法就稍微复杂了些,因为这也是核心内容。set方法在内部类ThreadLocalMap中,所以接下来分析下这个ThreadLocalMap类。
ThreadLocalMap
这个类在构造中创建了一个数组, new Entry[INITIAL_CAPACITY]; ,Entry里面就是一个object的对象,然后里面主要getEntry和set方法进行存取和读取。““
private void set(ThreadLocal key, Object value) {
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)]) { ThreadLocal k = e.get(); if (k == key) {//这里判断这个k和传进来的key是否相等 e.value = value;//进行存储后return return; } if (k == null) { replaceStaleEntry(key, value, i); return; } } tab[i] = new Entry(key, value); int sz = ++size; if (!cleanSomeSlots(i, sz) && sz >= threshold) rehash(); }
““
看主要代码 判断k和传进来的key相等话就存储这个value
get方法:
“`
private Entry getEntry(ThreadLocal
我们再看get:
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(); }
get里面也是要先获取当前的Thread这也就是为什么ThreadLocal获取和存储的都是只在当前线程的。
然后也是getMap方法获取这个ThreadLocalMap,这也就是为什么里面就一行代码,也要写成一个方来,因为这是中思路,其他地方获取直接调用就行,日后扩展的话一样方便。
再然后就是通过这个map去调用上面说的getEntry方法。
至此,我们就知道ThreadLocal的总体工作流程和思路了。
相关文章推荐
- C++类内部存储分析(含源码)(原创+转载)
- Muduo网络库源码分析(三)线程间使用eventfd通信和EventLoop::runInLoop系列函数
- 线程本地存储(Thread Local Storage, TLS)分析与使用
- java学习之旅57、58--数组_StringBuilder和StringBuffer的使用_JDK源码分析内部机制、常用方法补充_常见面试题答法
- Muduo网络库源码分析(三)线程间使用eventfd通信和EventLoop::runInLoop系列函数
- 第二人生的源码分析(四十一)使用Apache运行库线程
- 线程本地存储(Thread Local Storage, TLS)简单分析与使用
- Android之HandlerThread源码分析和简单使用(主线程和子线程通信、子线程和子线程通信)
- 线程本地存储(Thread Local Storage, TLS)简单分析与使用
- 第二人生的源码分析(四十一)使用Apache运行库线程
- 第二人生的源码分析(四十一)使用Apache运行库线程
- 分析balde源码,查看Web工程处理Ioc注入的背后的过程,ThreadLocal 使用保存线程所有的request and respond,
- java中使用线程实现Timer(定时器)原理和源码
- 国际化使用UTF-8造成数据库MSSQL Server 2000/2005存储乱码的分析
- Java:使用匿名内部类在方法内部定义并启动线程
- .NET / Rotor源码分析5 - 开始使用WinDbg+SOS调试,sscoree.dll,加载SOS并设置JIT断点
- .NET / Rotor源码分析5 - 开始使用WinDbg+SOS调试,sscoree.dll,加载SOS并设置JIT断点
- java中使用线程实现Timer(定时器)原理和源码
- .NET / Rotor源码分析5 - 开始使用WinDbg+SOS调试,sscoree.dll,加载SOS并设置JIT断点
- java中使用线程实现Timer(定时器)原理和源码