• 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中的,不清除越来越对炸了

  • 相关阅读:
    滑雪
    CSS被误删了 心态炸了。
    About Me
    偶数个3|递归|递推
    luogu P3200 [HNOI2009]有趣的数列|Catalan数|数论
    Sumdiv|同余|约数|拓展欧几里得算法
    博弈论
    友链——大佬们的博客
    【翻译】PalmOS 的PDB格式文件
    用acme.sh给ssl证书续期
  • 原文地址:https://www.cnblogs.com/mxz1994/p/13347614.html
Copyright © 2020-2023  润新知