大略的看了个大概,ThreadLocal.ThreadLocalMap内部的实现细节后边补充
理解:
线程的本地变量,赋值之后,多个线程之间的值不可见。 结合线程池使用时线程结束时要清除本次使用的本地变量。
整体:每个线程内部维护了一个ThreadLocal.ThreadLocalMap的变量threadLocals(key:ThreadLocal,value),ThreadLocal赋值取值时操作的其实都是该变量,该变量是每个线程的私有变量,必然不同线程之间不可见。
ThreadLocal threadLocal = new ThreadLocal<>();
1、threadLocal.set()
set方法中,首先获取当前线程ThreadCurrent.currentThread(),然后getMap(Threadt)获取获取线程的ThreadLocal.ThreadLocalMap 变量,不为空,set值key为当前的TheadLocal实例,value为传入的value值,为空创建一个空的ThreadCurrent.currentThread()并赋值。
2、threadLocal.get()
先获取当前线程ThreadCurrent.currentThread();获取当前线程的ThreadLocal.ThreadLocalMap 变量,若为空,返回空值,若不为空,根据当前的TheadLocal实例获取对应的value值
3、threadLocal.remove() 从当前线程中移除以当前ThreadLocal的实例为key的值
应用实例:mysql动态数据源切换
需求:根据已有的主从数据库环境,将部分查询请求分散到从库上。
此处只给出大概思路,并不贴出详细
思路:自定义注解+切面+ ThreadLocal+AbstractRoutingDataSource(动态数据源)
在mybatis接口方法上添加自定义注解,通过切面在执行前获取切面上的参数(动态数据源的key),ThreadLocal将获取的key写入本地线程变量,DynamicRoutingDataSource在获取连接时从ThreadLocal读取当前查询指定的数据源。
自定义注解:
切面:
记得切面后清除线程的本地变量
重写AbstractRoutingDataSource的determineCurrentLookupKey方法,从ThreadLocal中获取指定的数据源的key
另外动态数据源的配置: