美文网首页
ThreadLocal

ThreadLocal

作者: packet | 来源:发表于2019-10-28 13:17 被阅读0次

    ThreadLocal<>适用于什么场景?

    1. 每个线程都有自己的拷贝实例,其他线程不能访问。
    2. 方便在线程内部传递。
      其实可以在线程内部new一个对象来实现这个需求,但是这样会产生大量的样板代码,这样ThreadLocal就应运而生了。

    怎么用?来个栗子

    public class SessionHandler {
        private static ThreadLocal<Session> threadLocal = ThreadLocal.withInitial(() -> null);
        private static ThreadLocal<Session> another = new ThreadLocal() {
            protected Session initialValue() {
                return null;
            }
        };
    
        public Session get() {
            return threadLocal.get();
        }
    
        public void set(Session session) {
            threadLocal.set(session);
        }
    
        public void remove() {
            threadLocal.remove();
        }
    }
    

    原理是什么?需要游向代码深水区一探究竟。

    public class ThreadLocal<T> {
        protected T initialValue() {
            return null;
        }    
    
    
        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<?>> {
                /** The value associated with this ThreadLocal. */
                Object value;
    
                Entry(ThreadLocal<?> k, Object v) {
                    super(k);
                    value = v;
                }
            }
        }   
    
        private T setInitialValue() {
            T value = initialValue();
            Thread t = Thread.currentThread();
            ThreadLocalMap map = getMap(t);
            if (map != null)
                map.set(this, value);
            else
                createMap(t, value);
            return value;
        } 
    
        void createMap(Thread t, T firstValue) {
            t.threadLocals = new ThreadLocalMap(this, firstValue);
        }    
    
    
        public T get() {
            Thread t = Thread.currentThread();
            ThreadLocalMap map = getMap(t);
            if (map != null) {
                ThreadLocalMap.Entry e = map.getEntry(this);
                if (e != null) {
                    @SuppressWarnings("unchecked")
                    T result = (T)e.value;
                    return result;
                }
            }
            return setInitialValue();
        }
    }        
    
    public class Thread implements Runnable {
        ThreadLocal.ThreadLocalMap threadLocals = null;
    }
    
    

    原来Thread内部有一个成员ThreadLocal.ThreadLocalMap threadLocals,所以每个线程都有自己的map,这样就不会冲突。这个map类似HashMap,本质是一个Entry[],key和value都存储在Entry里,key是ThreadLocal,value是泛型。这个map不会发生哈希碰撞。
    为什么要构建一个map,因为thread可能需要多个threadLocal,那这些threadLocal会冲突吗?
    还有会造成内存泄露吗?

    参考:ThreadLocal和ThreadLocalMap源码分析

    相关文章

      网友评论

          本文标题:ThreadLocal

          本文链接:https://www.haomeiwen.com/subject/mmzvvctx.html