如何优雅的实现ThreadLocal

大部分翻译自How is ThreadLocal implemented?对代码作了更新
这是一个关于跳脱固有框架思考的例子,建议你花5分钟阅读全文,一定有所收获

ThreadLocal介绍

Implements a thread-local storage, that is, a variable for which each thread has its own value. All threads share the same {@code ThreadLocal} object ,but each sees a different value when accessing it, and changes made by one thread do not affect the other threads. The implementation supports {@code null} values.

大概意思是说,一个ThreadLocal变量可以为不同的线程保存不同的值

实现

通过介绍可知,可以为线程保存本地变量,那么我们可能需要一个Map对象,即ThreadLocal<T>变量内部维护一个HashMap<Thread,T>对象,其中,KEY可以通过Thread.currentThread()来获取,但是HashMap不是线程安全的,我们可以用Hashtable(相当于为每个方法加了同步原语synchronize的HashMap,效率低)或者ConcurrentHashMap(锁分段技术,效率高点)代替,一旦你使用这样的方式实现,那么需要面对的问题有两:

  • 1、内存泄漏风险,因为KEY为Thread
  • 2、同步的开销

为了解决第一个问题可以考虑使用弱应用替代Thread的强引用,但关于同步的开销明显是没有更好的方法解决了?

但实际上JDK中的实现并不是这样的且更加优雅,前面我们考虑以Thread作为KEY记录在ThreadLocal来为Thread保存线程独有的变量,而JDK的实现则是刚好与我们相反,用Thread来记录这样的一个以ThreadLocal-Object的映射关系(不一定是用JAVA中的Map容器来实现)

以Android23的为例子

public class Thread implements Runnable {
    ThreadLocal.Values localValues;
    // cut for brevity
}
public class ThreadLocal<T> {
    // cut for brevity
    static class Value {        
        private Object[] table;

        void put(ThreadLocal<?> keys, Object value) {
            cleanUp();
            int firstTombstone = -1;
            for (int index = key.hash & mask;; index = next(index)) {
                Object k = table[index];

                if (k == key.reference) {
                    // Replace existing entry.
                    table[index + 1] = value;
                    return;
                }
              }
            }//end put

            //........

        }//end Value

    public void set(T value) {
        Thread currentThread = Thread.currentThread();
        Values values = values(currentThread);
        if (values == null) {
            values = initializeValues(currentThread);
        }
        values.put(this, value);
    }

    Values initializeValues(Thread current) {
        return current.localValues = new Values();
    }

    // ...
}//end ThreadLocal

Thread记录了一个ThreadLocal.Value实例,用来记录了[ThreadLocal实例-线程本地变量]的映射,Key为hash值,不用担心内存泄漏问题,并且避免了同步所带来的开销问题,的确是十分优雅的实现

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 从三月份找实习到现在,面了一些公司,挂了不少,但最终还是拿到小米、百度、阿里、京东、新浪、CVTE、乐视家的研发岗...
    时芥蓝阅读 42,367评论 11 349
  • 前言 ThreadLocal很多同学都搞不懂是什么东西,可以用来干嘛。但面试时却又经常问到,所以这次我和大家一起学...
    liangzzz阅读 12,505评论 14 228
  • Java SE 基础: 封装、继承、多态 封装: 概念:就是把对象的属性和操作(或服务)结合为一个独立的整体,并尽...
    Jayden_Cao阅读 2,140评论 0 8
  • Android Handler机制系列文章整体内容如下: Android Handler机制1之ThreadAnd...
    隔壁老李头阅读 7,678评论 4 30
  • 管理界有句很经典的话:走多远,都别忘了当初为什么出发。于爱情婚姻而言,同样适用。 今天是高晴和苏晓结婚的5293天...
    九月雏菊阅读 6,580评论 0 11