ThreadLocal

来源:互联网 发布:安卓6.0短信拦截源码 编辑:程序博客网 时间:2024/06/19 06:09

ThreadLocal类解决的是变量在不同线程间的隔离性,每个线程拥有自己的不同值。Java.lang.ThreadLocal类来实现线程本地存储的功能。ThreadLocal为每个使用该变量的线程中都创建了一个副本,那么每个线程可以访问自己内部的副本变量每个线程内部都会有一个该变量,且在线程内部任何地方都可以使用,线程之间互不影响,这样一来就不存在线程安全问题,也不会严重影响程序执行性能。

每一个线程的Thread对象中都有一个ThreadLocalMap对象,这个对象存储了一组以ThreadLocal.threadLocalHashCode为键,以本地线程变量为值的K-V值对。ThreadLocal对象就是当前线程的ThreadLocalMap的访问入口,每一个ThreadLocal对象都包含了一个独一无二的threadLocalHashCode的值,使用这个值就可以在线程K-V值对中找回对应的本地线程变量。

get()方法是用来获取ThreadLocal在当前线程中保存的变量副本,set()用来设置当前线程中变量的副本,remove()用来移除当前线程中变量的副本,initialValue()是一个protected方法,一般是用来在使用时进行重写的,它是一个延迟加载方法。操作的步骤都是先取得当前线程t,然后通过getMap(t)方法获取到一个map,map的类型为ThreadLocalMap。然后接着下面获取到<key,value>键值对。

总结:实际上通过ThreadLocal创建的副本是存储在每个线程自己内ThreadLocalMap类型对象中的。ThreadLocalMap的键值为ThreadLocal对象的原因是每个线程中可有多个ThreadLocal变量。http://www.cnblogs.com/dolphin0520/p/3920407.html

最常见的ThreadLocal使用场景是用来解决数据库连接、Session管理等

public class Test {    ThreadLocal<Long> longLocal = new ThreadLocal<Long>();    ThreadLocal<String> stringLocal = new ThreadLocal<String>();          public void set() {        longLocal.set(Thread.currentThread().getId());        stringLocal.set(Thread.currentThread().getName());    }         public long getLong() {        return longLocal.get();    }         public String getString() {        return stringLocal.get();    }         public static void main(String[] args) throws InterruptedException {        final Test test = new Test();                          test.set();        System.out.println(test.getLong());        System.out.println(test.getString());Thread thread1 = new Thread(){            public void run() {                test.set();                System.out.println(test.getLong());                System.out.println(test.getString());            };        };        thread1.start();        thread1.join();                 System.out.println(test.getLong());        System.out.println(test.getString());    }}

输出结果如下:


解释:在这段代码中由两个ThreadLocal变量分别是longLocal和stringLocal,这两个变量在thread1和main线程中都保存了自己的变量副本,且变量的值在两个线程之间相互隔离在每个线程内部,把自己线程内部的longLocal变量和stringLocal变量存储在该线程内部的ThreadLocalMap对象中,在这个ThreadLocalMap对象中存储的内容是ThreadLocal.threadLocalHashCode为键,以本地线程变量为值的K-V值对,例如在上面的例子中thread1内的ThreadLocalMap对象存储的内容是<longLocal对象的hashcode值,thread1线程内的longLocal的值8>,<stringLocal对象的hashcode值,thread1线程内的stringLoccal的值Thread-0>,在main线程内的ThreadLocalMap对象存储的内容是<longLocal对象的hashcode值,main线程内的longLocal的值1>,<stringLocal对象的hashcode值,thread1线程内的stringLoccal的值main>。每个线程内部可以有多个threadLocal变量,在ThreadLocalMap中以ThreadLocal变量的hash值为键,以该值在该线程内部的变量为值的<key,value>对。

补充:使用InheritableThreadLocal类可以让子线程从父线程中取得值,但是继承之后在父线程或子线程中再修改就互不影响了。《Java多线程编程核心技术》


下面这个链接是介绍了ThreadLocal变量以及是否会发生内存泄漏。
http://qifuguang.me/2015/09/02/[Java并发包学习七]解密ThreadLocal/
0 0