多线程之---ThreadLocal

1、使用  通过set()方法设置属性,通过get()方法获取,remove()方法删除
2、源码:get()--获取
        public T get() {
               Thread t = Thread.currentThread();//获取当前线程
               ThreadLocalMap map = getMap(t);///获得当前线程里面的局部变量ThreadLocal.ThreadLocalMap
               if (map != null) {
                   ThreadLocalMap.Entry e = map.getEntry(this);//map存在 通过this 获取对应的value值
                   if (e != null) {
                       @SuppressWarnings("unchecked")
                       T result = (T)e.value;
                       return result;
                   }
               }
               return setInitialValue();//
           }

    //getMap方法
 ThreadLocalMap getMap(Thread t) {
        return t.threadLocals;//获得是Thread类的局部变量
    }
    //设置初始值  通过重新这个方法 来设置初始值
  protected T initialValue() {
        return null;
    }
    remove():---删除
    public void remove() {
             ThreadLocalMap m = getMap(Thread.currentThread());//根据当前线程获取ThreadLocalMap
             if (m != null)
                 m.remove(this);//删除对应的key值
         }
    set();---设置
     public void set(T value) {
            Thread t = Thread.currentThread();//获取当前线程
            ThreadLocalMap map = getMap(t);//获取当前线程的局部变量ThreadLocalMap
            if (map != null)
                map.set(this, value);//设置key值为当前ThreadLocal变量 value值为变量value
            else
                createMap(t, value);
        }
       初始化的时候 创建map方法:
void createMap(Thread t, T firstValue) {
        t.threadLocals = new ThreadLocalMap(this, firstValue);
    }

跟ThreadLocalMap关系:----ThreadLocal里面的一个内部类 key值为ThreadLocal变量 value为要保存的变量值
        1、在每个线程Thread内部有一个ThreadLocal.ThreadLocalMap类型的成员变量threadLocals,
        threadLocals就是用来存储实际的变量副本的,键值为当前ThreadLocal变量,value为变量副本(即T类型的变量)。
        2、初始时,在Thread里面,threadLocals为空,当通过ThreadLocal变量调用get()方法或者set()方法,就会对Thread类中的threadLocals进行初始化
        ,并且以当前ThreadLocal变量为键值,以ThreadLocal要保存的副本变量为value,存到threadLocals。
        3、在当前线程里面,如果要使用副本变量,就可以通过get方法在threadLocals里面查找。

3、ThreadLocal不是用来解决共享对象的多线程访问问题,他是保证线程安全的方式---线程封闭的应用之一。【通过set()方法放到线程中的对象是
   该线程自己使用的对象,其他线程访问不了的;通过get()方法  各线程从自己的map里面获取放进去的对象;通过threadLocal作为key值 每个线程中可有多个threadLocal变量,在
   每个线程里面的threadLocalMap里面 设置多个】
   应用场景:解决 数据库连接、Session管理
    private static final ThreadLocal threadSession = new ThreadLocal();

    public static Session getSession() throws InfrastructureException {
        Session s = (Session) threadSession.get();
        try {
            if (s == null) {
                s = getSessionFactory().openSession();
                threadSession.set(s);
            }
        } catch (HibernateException ex) {
            throw new InfrastructureException(ex);
        }
        return s;
    }
ThreadLocal不是用来解决对象共享访问问题的,而主要是提供了保持对象的方法和避免参数传递的方便的对象访问方式【空间换时间 保证线程安全的一种方式】。归纳了两点:
1。每个线程中都有一个自己的ThreadLocalMap类对象,可以将线程自己的对象保持到其中,各管各的,线程可以正确的访问到自己的对象。
2。将一个共用的ThreadLocal静态实例作为key,将不同对象的引用保存到不同线程的ThreadLocalMap中,然后在线程执行的各处通过这个静态ThreadLocal实例的get()方法取得自己线程保存的那个对象,避免了将这个对象作为参数传递的麻烦。

猜你喜欢

转载自blog.csdn.net/u011220648/article/details/81062617