ThreadLocal

一、ThreadLocal原理

    1.ThreadLocal:线程本地变量,对于同一个ThreadLocal,每个线程通过get/set/remove方法操作时只会影响自身线程的数据。
    2.ThreadLocalMap:key为ThreadLocal对象的弱引用,value为要存储的变量值。类似HashMap的数据结构(但它没有实现map接口,更不是hashmap的数据结构)。
    3.ThreadLocalMap是ThreadLocal的静态内部类Thread类有一个成员变量:ThreadLocal.ThreadLocalMap threadLocals = null;   在对ThreadLocal做set/get的时候,会通过:Thread t = Thread.currentThread(); 先拿到当前线程thread对象, 然后通过ThreadLocalMap map = getMap(t); 拿到这个Thread对象的成员变量ThreadLocalMap,再做set/get。
    4.实现:(1) ThreadLocal仅仅是个变量访问的入口,真正的变量副本绑定到当前Thread上的成员变量ThreadLocalMap里(这个ThreadLocalMap持有对象的引用);   (2) ThreadLocalMap以当前的threadLocal对象为key,以真正的存储对象为value。get()方法时通过threadLocal实例就可以找到绑定在当前线程上的副本对象。
    5.ThreadLocal+ThreadLocalMap设计的目的:保证当前线程结束时,相关对象可以立即被回收(弱引用)。

//ThreadLocal类的静态内部类ThreadLocalMap:
static class ThreadLocalMap {
	/**
	 * The table, resized as necessary.
	 * table.length MUST always be a power of two.
	 */
	private Entry[] table;    // 存储数据的数组

	private static final int INITIAL_CAPACITY = 16;    //map的默认大小

	// 存数据的结构: Entry对象, key是ThreadLocal对象的弱引用,value是那个值
	static class Entry extends WeakReference<ThreadLocal<?>> {

		Object value;    // The value associated with this ThreadLocal. 

		Entry(ThreadLocal<?> k, Object v) {    //构造方法
			super(k);
			value = v;
		}
	}

}

// ThreadLocal的set:
public void set(T value) {
	Thread t = Thread.currentThread();
	ThreadLocalMap map = getMap(t);    // 拿到当前线程的map
	if (map != null)
		map.set(this, value);          // 放KV: K是当前ThreadLocal对象的弱引用,V是value
	else
		createMap(t, value);
}

// ThreadLocal的get:
public T get() {
	Thread t = Thread.currentThread();
	ThreadLocalMap map = getMap(t);    // 拿到当前线程的map
	if (map != null) {
		ThreadLocalMap.Entry e = map.getEntry(this); // 拿到当前TreadLocale对象的弱引用对应的Entry
		if (e != null) {
			@SuppressWarnings("unchecked")
			T result = (T)e.value;
			return result;
		}
	}
	return setInitialValue();
}

    6.为什么要用弱引用:减少内存泄露(外部强引用消失时,Entry的key会变成null;否则该ThreadLocal对象一直不会被清理除非线程销毁了,线程池中长时间不销毁,内存泄露的问题会累积)。真正避免内存泄露:及时调用ThreadLocal的remove方法/及时销毁线程

    7.ThreadLocal和其他同步机制(syn/lock):
        同:解决多线程中并发访问的冲突;
        异:  通过控制线程对共享资源的访问时间解决冲突 & 从空间上隔离数据

 

项目中的使用:    设置动态数据源:部分接口只有查询且可以在从库进行查询时(查agent基础数据、配置的快捷话术等),通过ThreadLocal修改访问的DB配置,然后在退出的时候还原配置,达到只有这个线程访问从库的效果。

           数据源类型放在ThreadLocal中;
           继承AbstractRoutingDataSource抽象类,重写determineCurrentLookupKey()方法,在这里返回ThreadLocal里面的key。

      determineCurrentLookupKey()无法在事务中运行(动态切换失效),因为事务需要连接,并且该方法的目的是确定使用哪个DataSource来获取连接。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值