一、ThreadLocal简单介绍
首先,ThreadLocal是用来维护本线程的变量的,并不能解决共享变量的并发问题。ThreadLocal是各线程将值存入该线程的map中,以ThreadLocal自身作为key,需要用时获得的是该线程之前存入的值。如果存入的是共享变量,那取出的也是共享变量,并发问题还是存在的。
简单看一下例子:
public class TestThreadLocal {
private static final ThreadLocal<String> threadLocalA = new ThreadLocal<>();
private static final ThreadLocal<String> threadLocalB = new ThreadLocal<>();
/**
* 在调用的线程的map中存入key为ThreadLocal本身,value为在该线程设置的值
* @param value
*/
public static void setValueA(String value){
threadLocalA.set(value);
}
public static String getValueA(){
return threadLocalA.get();
}
public static void clearValueA(){
threadLocalA.remove();
}
public static void setValueB(String value){
threadLocalB.set(value);
}
public static String getValueB(){
return threadLocalB.get();
}
public static void clearValueB(){
threadLocalB.remove();
}
public static void main(String[] args) {
//线程1的ThreadLocalMap中存着key为threadLocalA,value为A1;key为threadLocalB,value为B1
new Thread(){
@Override
public void run(){
setValueA("A1");
System.out.println("thread1:" + getValueA());
clearValueA();
setValueB("B1");
System.out.println("thread1:" + getValueB());
clearValueB();
}
}.start();
//线程2的ThreadLocalMap中存着key为threadLocalA,value为A2;key为threadLocalB,value为B2
new Thread(){
@Override
public void run(){
setValueA("A2");
System.out.println("thread2:" + getValueA());
clearValueA();
setValueB("B2");
System.out.println("thread2:" + getValueB());
clearValueB();
}
}.start();
}
}
该例子的执行结果为:
thread2:A2
thread2:B2
thread1:A1
thread1:B1
从该例子可以看出多个线程设置ThreadLocal的值只在该线程的作用范围内有效。操作ThreadLocal的set,get方法实际上是操作该线程的一个代理,其本质是在该线程的ThreadLocalMap中存储了key为ThreadLocal本身和对应的值。
以下是ThreadLocal中的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);
}
ThreadLocalMap getMap(Thread t) {
return t.threadLocals;
}
要使用ThreadLocal维护数据源类 的原因:
,如果将key作为静态变量那可能引起并发问题,当同时访问数据库时,一个线程刚刚设置的key可能被另一个线程修改了,导致最终访问的数据源不正确。那么怎么样才能保证key能不被其它线程修改呢,即不能控制并发也不能每个线程都实例化DynamicDataSource来设置该线程的key,这时候ThreadLocal就能起到很好的作用,保护该线程私有的变量。