高端网站设计百家号,网站 费用,中关村手机之家报价,自助wap建站1.原理 ThreadLocal是用来保存当前线程数据的#xff0c;每一个线程的内部都有一个ThreadLocalMap#xff0c;当前这个map中存储了以当前ThreadLocal作键#xff0c;具体的数据作值的一个个Entry对象。 为什么非得以ThreadLocal对象作键呢#xff1f;因为一个线程可能使用了…1.原理 ThreadLocal是用来保存当前线程数据的每一个线程的内部都有一个ThreadLocalMap当前这个map中存储了以当前ThreadLocal作键具体的数据作值的一个个Entry对象。 为什么非得以ThreadLocal对象作键呢因为一个线程可能使用了不止一个ThreadLocal对象如果以当前线程对象做键再去找对应的ThreadLocal就很麻烦产生混淆。 由于每一个线程都有属于自己的ThreadLocal线程局部变量所以很好的实现了线程之间的数据隔离ThreadLocal中保存的数据仅属于当前线程。
2.ThreadLocal中的常见方法 1存储数据 set 2获取数据 get 3清除数据 remove 那么问题来了具体是怎样利用ThreadLocalMap查找数据的呢不论是set、get、remove等方法对当前map进行操作时最终都定位到了通过计算出的下标来操作。 而这个下标是通过哈希算法计算得到的操作ThreadLocalMap是以当前的ThreadLocal作key通过当前的key的HashCode值和Entry[]数组长度-1作“”运算来计算出实际操作位置的下标从而达到访问元素的目的。 作按位与运算的效果和利用哈希值直接进行取余%运算一样但效率上大大提高。
3.如何实现父子线程共享数据 利用了jdk提供ThreadLocal的子类InheritableThreadLocal来实现。
public class ThreadLocalTest {public static void main(String[] args) {InheritableThreadLocalString threadLocal new InheritableThreadLocalString();threadLocal.set(风萧萧兮易水寒);System.out.println(main主线程:threadLocal.get());Thread thread new Thread(new Runnable() {Overridepublic void run() {System.out.println(子线程:threadLocal.get());}});thread.start();}
} main函数为父线程创建了一个thread子线程利用InheritableThreadLocal这个子类来共享父线程的数据。 父线程子线程均输出“风萧萧兮易水寒”。
4.ThreadLocal如何避免内存泄露 执行完相关的业务逻辑后最终在finally代码块中都会调用remove方法将当前map中的ThreadLocal键置为空value置为空从而在垃圾回收的时候及时回收无用数据。
5.应用 1 线程的数据隔离 因为ThreadLocal对象只属于当前线程那么ThreadLocal中的数据也属于当前线程在多线程并发的情况下很好的实现了不同线程的数据隔离避免了采用synchronized锁机制来保证线程安全而导致的性能上的代价。 例如SqlSession会话对象绑定避免多个线程使用同一个SqlSession对象由于关闭导致异常。
//当前线程的线程局部变量
private static final ThreadLocal threadSession new ThreadLocal();public static SqlSession getSession(){//获取session会话方法SqlSession s (SqlSession)threadSession.get();//通过仅属于当前线程的threadSession对象来获取if(snull){//为空s getSqlSessionFactory().openSqlSession();//则重新建立会话threadSession.set(s);//并存到ThreadLocalMap中去}
} 2跨函数调用 数据通常用于同一个类中的传递如果利用方法传递势必要关心方法的返回值类型及参数但利用ThreadLocal可以直接实现获取这样做还达到了解耦的效果。 例如RequestContextHolder源码就有很好的体现
Nullable
public static RequestAttributes getRequestAttributes() {// 获取当前线程中的存储的Request Attribute//直接通过ThreadLocal对象来获取RequestAttributes attributes requestAttributesHolder.get(); if (attributes null) { attributes inheritableRequestAttributesHolder.get(); } return attributes;
}private static final ThreadLocalRequestAttributes requestAttributesHolder new NamedThreadLocal(Request attributes); private static final ThreadLocalRequestAttributes inheritableRequestAttributesHolder new NamedInheritableThreadLocal(Request context);
以上就是我对ThreadLocal线程区域对象的粗略理解欢迎诸君共同探讨。