关于一些ThreadLocal的认识

ThreadLocal的主要实现如下:

ThreadLocal中有一个静态内部类,名为ThreadLocalMap,主要定义如下:

     * ThreadLocalMap is a customized hash map suitable only for
     * maintaining thread local values. No operations are exported
     * outside of the ThreadLocal class. The class is package private to
     * allow declaration of fields in class Thread.  To help deal with
     * very large and long-lived usages, the hash table entries use
     * WeakReferences for keys. However, since reference queues are not
     * used, stale entries are guaranteed to be removed only when
     * the table starts running out of space.
     */
    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> {
            /** The value associated with this ThreadLocal. */
            Object value;

            Entry(ThreadLocal k, Object v) {
                super(k);
                value = v;
            }
        }

注意看其中的说明:

  • ThreadLocalMap是个定制的HashMap,所以很多HashMap的实现,这里其实都有类似的东西。
  • ThreadLocalMap的Entrty元素,注意是WeakReference类型,想想weakReference的特点嘞,它跟SoftReference的区别就是:
    • SoftReference指向的对象,只有在内存不足时才会被GC回收掉。
    • 只有WeakReference指向的对象,在下次GC的时候一般就会回收掉。
      所以这个Entry继承WeakReference,应该只是为了当一个线程结束时,其对应的ThreadLocal数据会尽快的被释放掉。
  • Entry中的key值是ThreadLocal本身,value则是你需要存储的数据(Object类型),所以对应到HashMap,可以想到其hashcode就是key的hashcode。
  • 每个线程独享一个ThreadLocalMap,比如一个Thread的实现,里面定义了4个ThreadLocal,那么在实际代码运行过程中,只会有一个ThreadLocalMap实例,里面包含了至少4个Entry,分别对应上述的几个ThreadLocal对象。而多个Thread之间,ThreadLocalMap是不共用的,每个线程对象自己维护自己的ThreadLocalMap。
  • 关于ThreadLocalMap存放在哪儿,其实跟正常的java对象一样,都是存放在堆空间里,通过线程来获取,如下:
class Thread implements Runnable {
    /* Make sure registerNatives is the first thing  does. */
    private static native void registerNatives();
    static {
        registerNatives();
    }

    private volatile String name;
    ...
    /* ThreadLocal values pertaining to this thread. This map is maintained
     * by the ThreadLocal class. */
    ThreadLocal.ThreadLocalMap threadLocals = null;

  ...

通过线程对象 t.threadLocals就可以获取到整个ThreadLocalMap,然后再根据key值获取存入的结果。

  • 这里之前看的时候,没有仔细去看对应的实现,以为是放在线程在初始化的时候指定的-Xss分配的堆空间内,但是仔细看过代码之后,发现两者并无关联。这里还是理解不够深,-Xss指定的是Stack space,也就是栈空间,其中是不会存放对象的。

你可能感兴趣的:(关于一些ThreadLocal的认识)