zoukankan      html  css  js  c++  java
  • ThreadLocal

    ThreadLocal

    map 和thread 关联 map里面的键是threadLocal 对象, value 是值

    Thread ThreadLocalMap ThreaLocal 关系

    1. Thread内含ThreadLocalMap, 放入(this, value)
      ![](_assets/

    用处

    Spring的事务管理,用ThreadLocal存储Connection,从而各个DAO可以获取同一Connection,可以进行事务回滚,提交等操作。

    1. 先从对应线程上获取对应的ThreadLocalMap 从ThreadLocalMap 中根据ThreadLocal 键值 设置值
        public void set(T value) {
            Thread t = Thread.currentThread();
            ThreadLocalMap map = getMap(t);
            if (map != null)
                map.set(this, value);
            else
                createMap(t, value);
        }
        // 1个线程对应一个 ThreadLocalMap
        void createMap(Thread t, T firstValue) {
            t.threadLocals = new ThreadLocalMap(this, firstValue);
        }
        // ThreadLocalMap 
        ThreadLocalMap(ThreadLocal<?> firstKey, Object firstValue) {
            table = new Entry[INITIAL_CAPACITY];
            int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1);
            table[i] = new Entry(firstKey, firstValue);
            size = 1;
            setThreshold(INITIAL_CAPACITY);
        }
    

    强引用、软引用、弱引用和虚引用

    
        tab[i] = new Entry(key, value);
        static class ThreadLocalMap {
    
            /**
             * The entries in this hash map extend WeakReference, using
             * its main ref field as the key (which is always a
             * ThreadLocal object).  Note that null keys (i.e. entry.get()
             * == null) mean that the key is no longer referenced, so the
             * entry can be expunged from table.  Such entries are referred to
             * as "stale entries" in the code that follows.
             */
            static class Entry extends WeakReference<ThreadLocal<?>> {
                Object value;
                Entry(ThreadLocal<?> k, Object v) {
                    super(k);
                    value = v;
                }
            }
    

    WeakReference对应用的对象userInfoLocal是弱引用,不会影响到userInfoLocal的GC行为。如果是强引用的话,在线程运行过程中,我们不再使用userInfoLocal了,将userInfoLocal置为null,但userInfoLocal在线程的ThreadLocalMap里还有引用,导致其无法被GC回收(当然,可以等到线程运行结束后,整个Map都会被回收,但很多线程要运行很久,如果等到线程结束,便会一直占着内存空间)。而Entry声明为WeakReference,userInfoLocal置为null后,线程的threadLocalMap就不算强引用了,userInfoLocal就可以被GC回收了。map的后续操作中,也会逐渐把对应的"stale entry"清理出去,避免内存泄漏。
    实际上只要ThreadLocal被定义成static的,那个WeakReference就是没有用的。因为static字段就是强引用,并且只要class load之后就永远可达
    那个WeakReference可能有用的时候是ThreadLocal不被定义为static的,它被作为参数在方法之间以及各线程之间传递。等到所有线程都不再能访问到它了,GC会把它回收。但是此时map里的那个entry还在,它包裹的对象是null了,那个value值也还在。它会在下一次expungeStaleEntry时被从map中清理掉。

    ThreadLocalMap内部Entry中key使用的是对ThreadLocal对象的弱引用,这为避免内存泄露是一个进步,因为如果是强引用,那么即使其他地方没有对ThreadLocal对象的引用,ThreadLocalMap中的ThreadLocal对象还是不会被回收,而如果是弱引用则这时候ThreadLocal引用是会被回收掉的,虽然对于的value还是不能被回收,这时候ThreadLocalMap里面就会存在key为null但是value不为null的entry项,虽然ThreadLocalMap提供了set,get,remove方法在一些时机下会对这些Entry项进行清理,但是这是不及时的,也不是每次都会执行的,所以一些情况下还是会发生内存泄露,所以在使用完毕后即使调用remove方法才是解决内存泄露的王道

    为什么使用完要清除:
    使用的是线程池,创建的ThradeLocal 是作为Key 放在线程绑定的ThradLocalMap中的,不清除越来越对炸了

  • 相关阅读:
    Win7 中出现图标显示不全或消失的解决方法
    动态控制ToolStrip上ToolStripButton的图标大小
    TS——类型断言
    TS——函数的类型
    TS之对象类型——接口
    TS——联合类型
    Git文件合并
    1-1、作用域深入和面向对象
    webStrom2017.1版本如何添加vue.js插件
    二:搭建一个webpack3.5.5项目:建立项目的webpack配置文件
  • 原文地址:https://www.cnblogs.com/mxz1994/p/13347614.html
Copyright © 2011-2022 走看看