`

ThreadLocal源码读后感总结

阅读更多

1.关联类

ThreadLocal: 线程局部变量

Thread:线程对象



2. Thread与ThreadLocal如何关联?

 ThreadLocal类:

 
   /**
     * Variant of set() to establish initialValue. Used instead
     * of set() in case user has overridden the set() method.
     *
     * @return the initial value
     */
    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;
    }

 /**
     * Create the map associated with a ThreadLocal. Overridden in
     * InheritableThreadLocal.
     *
     * @param t the current thread
     * @param firstValue value for the initial entry of the map
     * @param map the map to store.
     */
    void createMap(Thread t, T firstValue) {
        t.threadLocals = new ThreadLocalMap(this, firstValue);
    }
 

 

 

 Thread类:

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

 

在每一个线程中都声明了一个成员变量ThreadLocalMap,而它的创建则是在ThreadLocal中通过createMap实现。第一次直接通过构造方法保存对象,之后取得ThreadLocalMap的引用进行set,保存在entry中。



3.一个ThreadLocal保存一个线程变量

 

/**
     * ThreadLocals rely on per-thread linear-probe hash maps attached
     * to each thread (Thread.threadLocals and
     * inheritableThreadLocals).  The ThreadLocal objects act as keys,
     * searched via threadLocalHashCode.  This is a custom hash code
     * (useful only within ThreadLocalMaps) that eliminates collisions
     * in the common case where consecutively constructed ThreadLocals
     * are used by the same threads, while remaining well-behaved in
     * less common cases.
     */
    private final int threadLocalHashCode = nextHashCode();
 
 /**
     * Sets the current thread's copy of this thread-local variable
     * to the specified value.  Most subclasses will have no need to 
     * override this method, relying solely on the {@link #initialValue}
     * method to set the values of thread-locals.
     *
     * @param value the value to be stored in the current thread's copy of
     *        this thread-local.
     */
    public void set(T value) {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
    }

 

 

threadLocalHashCode是ThreadLocal的唯一标识,ThreadLocalMap将ThreadLocal做为key值,因此同一个ThreadLocal对应的value将有且仅有一个,并只保存最后一次value值。起初脑袋被门夹了,一直想不明白ThreadLocal无论你set多少次只保存最后一个对象,定义ThreadLocalMap仅仅用来保存一个对象?后来才发现,原来是钻牛角尖了,当前线程下多new 几个ThreadLocal不就行了(学艺不精,思维没打开啊)。



4.ThreadLocalMap中Entry继承了WeakReference

虽然实现了弱引用,在内存不够的时候,即使还被引用,也能被GC回收,但是最好习惯性手动调用下

       /**
         * Remove the entry for key.
         */
        private void remove(ThreadLocal key) {
            Entry[] tab = table;
            int len = tab.length;
            int i = key.threadLocalHashCode & (len-1);
            for (Entry e = tab[i];
		 e != null;
		 e = tab[i = nextIndex(i, len)]) {
                if (e.get() == key) {
                    e.clear();
                    expungeStaleEntry(i);
                    return;
                }
            }
        }
 

 

如果你所应用的环境中存在线程池,当前线程没被销毁。下个应用可能使用上个线程,可能会造成上个线程的数据显示在下个线程中。所以在结束使用ThreadLocal时,记得手动调用下remove


5.ThreadLocalMap保存算法

/**
         * Set the value associated with key.
         *
         * @param key the thread local object
         * @param value the value to be set
         */
        private void set(ThreadLocal key, Object value) {

            // We don't use a fast path as with get() because it is at
            // least as common to use set() to create new entries as
            // it is to replace existing ones, in which case, a fast
            // path would fail more often than not.

            Entry[] tab = table;
            int len = tab.length;
            int i = key.threadLocalHashCode & (len-1);

            for (Entry e = tab[i];
		 e != null;
		 e = tab[i = nextIndex(i, len)]) {
                ThreadLocal k = e.get();

                if (k == key) {
                    e.value = value;
                    return;
                }

                if (k == null) {
                    replaceStaleEntry(key, value, i);
                    return;
                }
            }

            tab[i] = new Entry(key, value);
            int sz = ++size;
            if (!cleanSomeSlots(i, sz) && sz >= threshold)
                rehash();
        }

 拿ThreadLocal的threadLocalHashCode与长度减一相与,求出哈希表的位置。如果这个插槽已有不为空的entry,则依次遍历之后的位置,当达到最大长度时,重新从第一个位置开始找,直到找着为null的插槽.增加size记录已有多少个元素,在查找过程中会判断这个entry弱引用是否已被回收,如果已回收则清楚value重新释放这个插糟并size-1,如果size等于加载因子则按2倍扩容。

 

 

6.总结

通过Thread.currentThread()取得当前线程,在这个线程中活动期间创建多个ThreadLocal放入当前线程的ThreadLocalMap中,相当于将多线程分开,每个人操作自己的线程,在自己线程中创建与使用自己的变量,各管各的,这就是所谓的“为每一个使用该变量的线程都提供一个变量值的副本,使每一个线程都可以独立地改变自己的副本”。

与synchronized相比只了解了其中之一的优点:“以空间换时间”。

ThreadLocal会随着线程的销毁而销毁

分享到:
评论

相关推荐

    ThreadLocal源码(版本:Android4.3,,含注释)

    ThreadLocal源码(版本:Android4.3,,含注释)

    threadlocal源码.jpg

    threadlocal源码解析

    Java并发编程学习之ThreadLocal源码详析

    Java并发编程学习之ThreadLocal源码详析 ThreadLocal是Java并发编程中的一种机制,用于解决多线程访问共享变量的问题。它可以使每个线程对共享变量的访问都是线程安全的,使得多线程编程变得更加简单。 ...

    ThreadLocal源码分析

    首先,ThreadLocal 不是用来解决共享对象的多线程访问问题的,一般情况下,通过ThreadLocal.set() 到线程中的对象是该线程自己使用的对象,其他线程是不需要访问的,也访问不到的。各个线程中访问的是不同的对象。

    ThreadLocal_ThreadLocal源码分析_

    **ThreadLocal概述** ThreadLocal是Java中的一个线程局部变量类,它为每个线程创建了一个独立的变量副本。这意味着每个线程都有自己的ThreadLocal变量,互不干扰,提供了线程安全的数据存储方式。ThreadLocal通常...

    ThreadLocal源码以及应用.md

    ThreadLocal源码以及应用

    ThreadLocal_ThreadLocal源码分析_源码.zip

    因此,使用完ThreadLocal后,最好显式调用`remove()`方法。 5. **线程局部变量的生命周期**:线程局部变量的生命周期与线程的生命周期相同,当线程结束后,其ThreadLocalMap也会被销毁,存储的变量也随之消失。 **...

    ThreadLocal源码分析和使用

    ThreadLocal 源码分析和使用 ThreadLocal 是 Java 语言中的一种多线程编程机制,用于解决多线程程序的并发问题。它不是一个 Thread,而是一个 Thread 的局部变量。ThreadLocal 的出现是为了解决多线程程序中的共享...

    ThreadLocal

    ThreadLocal是Java编程语言中的一个类,用于在多线程环境中提供线程局部变量。它是一种特殊类型的变量,每个线程都有自己的副本,互不影响,从而实现线程间数据隔离。ThreadLocal通常被用来解决线程共享数据时可能...

    理解的ThreadLocal类的相关源码(用于博文引用源码下载)

    Java中ThreadLocal工具类(解决多线程程序中并发问题的一种新思路,主要为参数的拷贝问题),感兴趣的话可以查看博文,博文地址:http://blog.csdn.net/otengyue/article/details/38459327

    java ThreadLocal多线程专属的变量源码

    java ThreadLocal多线程专属的变量源码java ThreadLocal多线程专属的变量源码java ThreadLocal多线程专属的变量源码java ThreadLocal多线程专属的变量源码java ThreadLocal多线程专属的变量源码java ThreadLocal多...

    Java源码解析ThreadLocal及使用场景

    Java源码解析ThreadLocal及使用场景 ThreadLocal是Java中一个非常重要的类,它在多线程环境下经常使用,用于提供线程本地变量。这些变量使每个线程都有自己的一份拷贝,使得多个线程可以独立地使用变量,不会彼此...

    ThreadLocal应用示例及理解

    - 使用ThreadLocal时,要特别注意线程结束后的清理工作,防止内存泄漏。 - 避免过度使用ThreadLocal,因为它会为每个线程创建额外的内存开销。 以上就是关于ThreadLocal的基本概念、使用方法、生命周期管理和实际...

    ThreadLocal的原理,源码深度分析及使用.docx

    ThreadLocal 的原理、源码深度分析及使用 ThreadLocal 是 Java 语言中的一种机制,用于实现线程本地存储,能够帮助开发者在多线程环境下解决变量访问安全的问题。下面将对 ThreadLocal 的原理、实现机制、使用方法...

    使用ThreadLocal管理“session”数据

    总结,ThreadLocal是Java中处理线程局部数据的利器,特别适用于需要线程隔离的场景,如Web应用中的session管理。通过合理使用ThreadLocal,可以提升程序的并发性能并保证数据安全性。但同时,需要注意内存管理和避免...

    ThreadLocal 内存泄露的实例分析1

    总结:`ThreadLocal` 是一个强大的工具,但在使用时必须谨慎,尤其是在多线程环境中,如 Tomcat 这样的 Web 容器。如果不正确地管理 `ThreadLocal` 的生命周期,可能导致类加载器级别的内存泄漏。理解 `ThreadLocal`...

    理解ThreadLocal

    理解ThreadLocal 理解ThreadLocal 理解ThreadLocal 理解ThreadLocal

    java并发包源码分析(3)ThreadLocal

    3. 在使用完ThreadLocal后,及时清理。例如,在finally块中进行清理操作,或者使用try-with-resources语句。 ### 知识点六:ThreadLocalMap的扩容和rehash 在ThreadLocalMap中,当Entry数组需要扩容时,会进行...

Global site tag (gtag.js) - Google Analytics