我是站长,从2003年开始接触计算机,至今已有16年。某重点大学硕士毕业。精通Java,C/C++,Python,熟悉Web开发,擅长大数据,对数学和英语情有独钟。本文是出自我的小册子:《一针见血ThreadLocal》。

1、ThreadLocal原理介绍

ThreadLocal的原理是什么呢?我相信肯定有些人会语塞,无从说起。即便心里有种朦胧的感觉,但是也说不清楚。

在《操作系统》课上我们学过:进程是资源的分配单位,线程是运行调度单位。也就是说,任何运行的程序,必定归属于某个线程。不管是main线程也好,还是其他的线程也罢。这一点要清楚。

程序跑起来,就会产生一个线程。在这个线程里面会有一个context上下文,我们可以往context里面存放东西,随后在线程管辖范围内都可以获取到。伪代码示例如下所示:


//此处是伪代码
Thread t = Thread.currentThread();

ThreadContext context = t.getContext();

//存数据
context.set(1000); 

//取数据
context.get();

线程本来就属于重型对象,现在还带个上下文,岂不是重上加重,胖的有点跑不动了。所以,jdk的作者耍了一个小聪明:用的时候再创建这个context上下文,不用则留个占位就行了。

如何实现这种“延迟创建线程上下文context”的目的呢?jdk作者采用的方案是:用threadlocal来负责创建上下文。

Thread t = Thread.currentThread();

ThreadContext context = t.getContext();

if ( context = null )
{
    context  = createContext();
}

既然线程上下文context是由threadlocal负责创建的,自然也有它来代理context的数据操作[set/get操作],所有出现了threadlocal.set()和threadlocal.get()方法。

延迟创建的问题已然解决,应该是皆大欢喜。但是总是有人高兴了过头,来了一个画蛇添足。threadlocal在set存数据到线程上下文context的时候,把自己[this]也放进去了,而且跟1000做出了key-value的形式。也就是这样的:


context.set(this,1000); 

本来为了让线程跑的更轻便,所以搞出一个延迟创建,现在倒好,又增加了配件。总之,线程上下文里面有两部分:有效载荷和threadlocal配件。

threadlocal放入线程上下文的时候,被弱引用包装了一下,虽然它被context所持有,但是不稳定,一旦外界没有人持有threadlocal引用,很容易被清空,key消失了,value还能找到吗?肯定不能了。这时候就发生了内存泄漏。

2、ThreadLocal用法介绍

threadlocal是线程上下文context的代理对象,context的目的是存放数据,自然threadlocal也是用来存放数据,所以主要用法就是set和get操作。

3、公众号

如果诸位从这篇文章读到了收获,恭喜您!欢迎关注网站的公众号:

标签: none

添加新评论