关于一些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<ThreadLocal<?>> {
            /** 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 <clinit> 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很多同学都搞不懂是什么东西,可以用来干嘛。但面试时却又经常问到,所以这次我和大家一起学...
    liangzzz阅读 12,488评论 14 228
  • Android Handler机制系列文章整体内容如下: Android Handler机制1之ThreadAnd...
    隔壁老李头阅读 7,665评论 4 30
  • 原创文章&经验总结&从校招到A厂一路阳光一路沧桑 详情请戳www.codercc.com 1. ThreadLoc...
    你听___阅读 6,759评论 8 19
  • ThreadLocal,线程变量,是一个以ThreadLocal对象为键,任意对象为值 的存储 结构。该结构附着于...
    Justlearn阅读 413评论 0 2
  • 我是一名河南郑州装修公司的项目负责人,30岁,男,2013年10月28号回的郑州,至今有3年多。已婚,生育一女。 ...
    马梦小璐阅读 208评论 0 0