ThreadLocal在很多地方都有使用过,今天看看它是如何来实现的。还是先通过一个小的例子看看用法,然后再分析其源码。
ThreadLocal有两个关键的方法:get()和set()。
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
*
* ThreadLocal用法示例
*
*/
class ThreadTask implements Runnable {
// ThreadLocal实例
ThreadLocal<String> locals = new ThreadLocal<String>();
@Override
public void run() {
if (locals.get() == null) {
locals.set(Thread.currentThread().getName() + "aaa");
}
System.out.println(locals.get());
}
}
public class ThreadLocalDemo {
public static void main(String args[]) {
// 线程池
ExecutorService exec = Executors.newFixedThreadPool(4);
for(int i=0;i<4;i++){
ThreadTask threadTask = new ThreadTask();
exec.submit(threadTask);
}
}
}
ThreadLocal有两个关键的方法:get()和set()。
public T get() {
// 获取当前线程
Thread t = Thread.currentThread();
// 获取ThreadLocalMap对象
ThreadLocalMap map = getMap(t);
if (map != null) {
// this就是ThreadLocal实例对象
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null)
return (T)e.value;
}
// 如果不存在就初始化
return setInitialValue();
}
private T setInitialValue() {
// 默认返回null值
T value = initialValue();
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
// this表示的是ThreadLocal实例对象
map.set(this, value);
else
// new ThreadLocalMap(),这里t就是当前线程
createMap(t, value);
return value;
}
public T get() {
Thread t = Thread.currentThread();
// 每个线程都有这样的一个ThreadLocalMap对象
ThreadLocalMap map = getMap(t);
if (map != null) {
// 然后通过ThreadLocal实例对象来查找其value值
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null)
return (T)e.value;
}
return setInitialValue();
}
所以从源码上就可以看出,ThreadLocal内部有一个ThreadLocalMap对象,每个线程都有这个对象ThreadLocalMap,这个map的key值是ThreadLocal实例对象,value就是存储的值。
在Spring 获取Connection时,它是这样在DataSourceUtils中应用的。
public static Connection doGetConnection(DataSource dataSource) throws SQLException {
// 这里调用TransactionSynchronizationManager.getResource()方法
// TransactionSynchronizationManager中resource是ThreadLocal类型
ConnectionHolder conHolder = (ConnectionHolder) TransactionSynchronizationManager.getResource(dataSource);
if (conHolder != null && (conHolder.hasConnection() || conHolder.isSynchronizedWithTransaction())) {
conHolder.requested();
if (!conHolder.hasConnection()) {
conHolder.setConnection(dataSource.getConnection());
}
return conHolder.getConnection();
}
return con;
}