java之ThreadLocal
来源:互联网 发布:pink原宿风拍照软件 编辑:程序博客网 时间:2024/06/18 10:58
1、概述
ThreadLocal类用来提供线程内部的局部变量。这些变量在多线程环境下访问(通过get或set方法访问)时能保证各个线程里的变量相对独立于其他线程内的变量,ThreadLocal实例通常来说都是private static类型。
总结:ThreadLocal不是为了解决多线程访问共享变量,而是为每个线程创建一个单独的变量副本,提供了保持对象的方法和避免参数传递的复杂性。
ThreadLocal的主要应用场景为按线程多实例(每个线程对应一个实例)的对象的访问,并且这个对象很多地方都要用到。例如:同一个网站登录用户,每个用户服务器会为其开一个线程,每个线程中创建一个ThreadLocal,里面存用户基本信息等,在很多页面跳转时,会显示用户信息或者得到用户的一些信息等频繁操作,这样多线程之间并没有联系而且当前线程也可以及时获取想要的数据。
每个thread中都存在一个map, map的类型是ThreadLocal.ThreadLocalMap. Map中的key为一个threadlocal实例. 这个Map的确使用了弱引用,不过弱引用只是针对key. 每个key都弱引用指向threadlocal. 当把threadlocal实例置为null以后,没有任何强引用指向threadlocal实例,所以threadlocal将会被gc回收. 但是,我们的value却不能回收,因为存在一条从current thread连接过来的强引用. 只有当前thread结束以后, current thread就不会存在栈中,强引用断开, Current Thread, Map, value将全部被GC回收.
所以得出一个结论就是只要这个线程对象被gc回收,就不会出现内存泄露,但在threadLocal设为null和线程结束这段时间不会被回收的,就发生了我们认为的内存泄露。其实这是一个对概念理解的不一致,也没什么好争论的。最要命的是线程对象不被回收的情况,这就发生了真正意义上的内存泄露。比如使用线程池的时候,线程结束是不会销毁的,会再次使用的。就可能出现内存泄露。
更多关于ThreadLocal文章介绍:
ThreadLocal和synchronized的区别
彻底理解ThreadLocal
深入研究java.lang.ThreadLocal类
2、ThreadLocal各个类之间的层级关系
class Thread {// 当前线程对象class ThreadLocalMap {// ThreadLocalMap对象,作为Thread的属性Entry[] table;// 存放多种threadLocal对象对应的值class Entry {//内部类Object value;// 需要存放的值ThreadLocal<T> key;// 以threadLocal作为key}}}
3、ThreadLocal中get、set方法源码分析
ThreadLocal get方法源码分析(在第一次调用theadlocal的get、set方法是都会创建ThreadLocalMap对象)
public T get() { Thread t = Thread.currentThread();//获取当前线程 ThreadLocalMap map = getMap(t);//根据当前线程对象获取threadLocalMap对象 if (map != null) { ThreadLocalMap.Entry e = map.getEntry(this);//获取Entry对象 if (e != null) { @SuppressWarnings("unchecked") T result = (T)e.value;//获取对应ThreadLocal的变量值 return result; } } return setInitialValue(); }
TheadLocalMap中getEntry方法源码
private Entry getEntry(ThreadLocal<?> key) { int i = key.threadLocalHashCode & (table.length - 1);//找到当前threadLocal对应下标 Entry e = table[i]; if (e != null && e.get() == key) return e; else return getEntryAfterMiss(key, i, e); }
setInitiaValue方法源码 private T setInitialValue() { T value = initialValue();//初始化值默认为null Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) map.set(this, value);//实例化Entry对象,包含threadLocal对象以及变量,并将Entry对象写入table数组 else createMap(t, value);//将当前线程Thread的TheadLocalMap对象实例化,新建一个Entry(threadLocal,value)对象并写入的table数组 return value; }
ThreadLcoal set方法源码分析
public void set(T value) { Thread t = Thread.currentThread();//获取当前线程对象 ThreadLocalMap map = getMap(t);//根据当前线程获取ThreadLocalMap对象 if (map != null) map.set(this, value);//将value值存入Entry[] table中 else createMap(t, value);//为当前线程新建ThreadLocalMap对象 }
private void set(ThreadLocal<?> key, Object value) { // We don't use a fast path as with get() because it is at // least as common to use set() to create new entries as // it is to replace existing ones, in which case, a fast // path would fail more often than not. 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) { e.value = value; return; } if (k == null) { replaceStaleEntry(key, value, i); return; } } tab[i] = new Entry(key, value);//实例化一个Entry对象 int sz = ++size; if (!cleanSomeSlots(i, sz) && sz >= threshold) rehash(); }
新建ThreadLocalMap对象源码
void createMap(Thread t, T firstValue) { t.threadLocals = new ThreadLocalMap(this, firstValue); }ThreadLocalMap(ThreadLocal<?> firstKey, Object firstValue) { table = new Entry[INITIAL_CAPACITY]; int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1); table[i] = new Entry(firstKey, firstValue); size = 1; setThreshold(INITIAL_CAPACITY); }
- Java 之 ThreadLocal学习
- Java多线程之ThreadLocal
- java 之 ThreadLocal学习
- Java多线程之ThreadLocal
- Java基础之ThreadLocal
- Java线程之ThreadLocal
- java之ThreadLocal笔记
- JAVA多线程之ThreadLocal
- java线程之ThreadLocal
- Java多线程之 ThreadLocal
- Java基础 之ThreadLocal
- java多线程之ThreadLocal
- Java基础之ThreadLocal
- Java多线程之----ThreadLocal
- Java多线程之ThreadLocal
- java并发之ThreadLocal
- java之ThreadLocal
- Java之:Threadlocal
- ssi(spring +struts2+ibatis) 增删改查,表连接,分页。
- Spring中文文档翻译Integration Testing(1)
- 项目报错:java web error:Choose unique values for the 'webAppRootKey' context-param in your web.xml files
- maven项目打成war发布到tomcat运行
- Ubuntu下安装RabbitMQ Server
- java之ThreadLocal
- IOS 上传App Store
- WebView常用配置和方法
- 云栖大会之异构计算,12日,B-3-5不见不散。
- 将 byte[] 转成Stream与将完整物理路径转成Stream
- 版本控制-Git安装与配置
- 从零一起学react(4)---组件的props和state
- html学习笔记1
- Saltstack部署和简介