一、什么是ThreadLocal类
ThreadLocal 在很多地方叫做本地变量,在有些地方叫做线程本地存储。ThreadLocal在每个线程中为每个变量都创建了一个副本,每个线程可以访问自己内部的副本变量,而不会对其它线程的副本变量造成影响。
二、例子
public class MyThreadLocal { //private static ThreadLocal<Integer> intLocal=new ThreadLocal<Integer>(); private static ThreadLocal<Long> longLocal = new ThreadLocal<Long>(); private static ThreadLocal<String> stringLocal = new ThreadLocal<String>(); public void set() { //将线程的id设置到ThreadLocal longLocal.set(Thread.currentThread().getId()); //将线程的Name设置到ThreadLocal stringLocal.set(Thread.currentThread().getName()); } public String getString() { //从ThreadLocal中取出线程的变量副本 return stringLocal.get(); } public Long getLong() { //从ThreadLocal中取出变量副本 return longLocal.get(); } public static void main(String[] args) { MyThreadLocal threadLocal = new MyThreadLocal(); threadLocal.set(); String string = threadLocal.getString(); System.out.println(Thread.currentThread().getName() + ": " + string); Long aLong = threadLocal.getLong(); System.out.println(Thread.currentThread().getId() + ": " + aLong); Thread thread = new Thread() { public void run() { threadLocal.set(); System.out.println(Thread.currentThread().getName() + ": " + threadLocal.getString()); System.out.println(Thread.currentThread().getId() + ": " + threadLocal.getLong()); } }; thread.start(); try { thread.join(); } catch (InterruptedException e) { e.printStackTrace(); } } }
运行结果:
如果看不懂没关系,下面会解释各个函数的意思。
三、ThreadLocal的方法
Public T get(){}
Public void set(T value){}
Public void remove(){}
Public T inittalValue(){}
Get()方法是用来获取ThreadLocal在当前线程中保存的变量副本,set()是用来设置当前线程中变量的副本,remove()是用来移除房钱线程中的变量副本,initialValue()是一个Protected方法,一般是用来在使用时进行重写的。
首先,在每个线程Thread内部都有一个ThreadLocal.ThreadLcoalMap 类型的成员变量threadLocals,该变量类似一个map,这个map妞儿会死用来存储实际的变量副本的,key存储每个ThreadLocal变量,value用来存储每个ThreadLocal存储的值即变量副本。
初始时,ThreadLocals为空,当通过ThreadLocal变量调用get()方法或set()方法,就会对Thread类中threadLocals进行初始化,并且以当前的ThreadLocal变量为键值,以ThreadLocal要保存的变量的副本变量为value,存到threadLocals。
总结:
通过ThreadLocal创建的副本存储在每个线程自己的threadLocals中
threadLocals中用每个ThreadLocal作为key,用每个ThreadLocal要存储的变量副本为value。
在进行get()方法之前,需要先进行set(),否则会报空指针异常。
ThreadLocal类的使用场景:
常用来解决数据库连接、Session管理。
参考资料: