ThreadLocal理解
来源:互联网 发布:世界著名ufo事件 知乎 编辑:程序博客网 时间:2024/06/08 09:39
首先举例说明ThreadLocal类的使用:
public class ThreadTest { static ThreadLocal<String> tLocal = new ThreadLocal<String>(); public static void main(String[] args) { // TODO Auto-generated method stub try { tLocal.set(Thread.currentThread().getName());//将main线程名称保存到tlocal中 //使用匿名类创建一个新线程 Thread thread = new Thread(){ public void run(){ tLocal.set(Thread.currentThread().getName()); System.out.println(tLocal.get()); } }; thread.start(); thread.join(); System.out.println(tLocal.get()); } catch (InterruptedException e) { // TODO: handle exception e.printStackTrace(); } }}
运行结果:
Thread-0Main
根据运行结果可知,在threadlocal中为每个线程存储一个单独的值。下面,结合上面例子,分析源码具体了解该类的原理:
首先threadlocal实例化,查看构造函数,没有任何其它操作。
public ThreadLocal() {}
Set()方法理解:
public void set(T value) { //获取当前线程 Thread t = Thread.currentThread(); //ThreadLocalMap是ThreadLocal的静态内部类,具体见下面getMap方法, //第一次执行该方法,map是null, ThreadLocalMap map = getMap(t); if (map != null) //具体见下面set方法 map.set(this, value); else //当map为null是,创建map,具体见下面的createMap源码 createMap(t, value);}//在Thread类中,定义了threadLocals变量ThreadLocal.ThreadLocalMap threadLocals = null;
ThreadLocalMap.set()方法:
private void set(ThreadLocal key, Object value) { //获取类型为Entry的table数组,Entry是ThreadLocalMap的内部类 Entry[] tab = table; int len = tab.length; //根据key的hash值与15做&运算,得出下标 int i = key.threadLocalHashCode & (len-1); //循环,当e不为null,执行循环体 for (Entry e = tab[i]; e != null; e = tab[i = nextIndex(i, len)]) { ThreadLocal k = e.get(); if (k == key) { e.value = value; return; } if (k == null) { replaceStaleEntry(key, value, i); return; } } //实例化Entry,赋给tab[i],其实threadlocal本质就是将每个线程中的 //theadlocal.threadlocalmap对象和共享的变量,形成entry对象, tab[i] = new Entry(key, value); int sz = ++size; //当table数组中的元素大于10,扩展table;即每个线程中的threadlocal //数量大于10时,会对table数组扩展 if (!cleanSomeSlots(i, sz) && sz >= threshold) rehash(); }
ThreadLocal.createMap(Thread t,T firstValue)方法:
//为每个线程创建ThreadLocalMap实例,void createMap(Thread t, T firstValue) { t.threadLocals = new ThreadLocalMap(this, firstValue); }//ThreadLocalMap构造函数,传入ThreadLocalMap(ThreadLocal firstKey, Object firstValue) { //创建Entry类型的数组,长度为16 table = new Entry[INITIAL_CAPACITY]; //获取存放Entry实例的下标 int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1); table[i] = new Entry(firstKey, firstValue); size = 1; //设置扩展table长度的阈值 setThreshold(INITIAL_CAPACITY); }
以上分析代码可知,ThreadLocal在多线程中的应用中的原理如下图:
根据图可知,每个线程中,都有自己独立的了ThreadLocalMap类的实例,ThreadLocalMap中的key是tLocal对象的引用,value表示每个线程中的独立的变量值,ThreadLocal的set方法的实质就是:若当前线程中ThreadLocalMap为null,则实例化ThreadLocalMap,同时传入ThreadLocal的引用和变量值;若不为null,执行ThreadLocalMap的set方法,同样需要传入ThreadLocal的引用和变量值。
当需要获取变量值时,调用ThreadLocal的get方法,自动获取当前线程中的ThreadLocalMap对象,并获取相应的变量值。
ThreadLocal并不是什么线程,确切地说是一个线程的变量,通过该变量,可以实现多线程之间的安全访问全局变量。ThreadLocal同synchronized,都是解决线程安全问题,ThreadLocal是通过“空间换取时间”的方式,synchronized是通过“时间换取空间”的方式。
- 理解ThreadLocal
- 理解ThreadLocal
- 理解ThreadLocal
- 理解ThreadLocal
- 理解ThreadLocal
- 理解ThreadLocal
- 理解ThreadLocal
- 理解ThreadLocal
- 理解ThreadLocal
- 理解ThreadLocal
- 理解Threadlocal
- 理解ThreadLocal
- 理解ThreadLocal
- 理解ThreadLocal
- 理解ThreadLocal
- 理解ThreadLocal
- 理解ThreadLocal
- 理解ThreadLocal
- 全角、半角字符长度验证
- 浅谈使用Fiddler工具发送post请求(带有json数据)以及get请求(Header方式传参)
- 自定义View
- c# 登录 防止sql注入 mysql数据库
- Ubuntu shutter截图像qq截图一样方便
- ThreadLocal理解
- 最短路径算法—Bellman-Ford(贝尔曼-福特)算法分析与实现(C/C++)
- 从0开始学Python——我的学习之路
- 更新服务器出现问题
- list<T>排列 排序
- python2.7 编码问题
- 验证从标准输入获得的信用卡号是否校验通过, 校验通过,则输出”成功“,校验未通过则输出”失败“
- LintCode 回文数
- 简单的计算器