当前位置: 首页 > 科技观察

大话ThreadLocal

时间:2023-03-14 19:54:28 科技观察

相传唐朝贞观年间,物富天宝,人杰地灵。太宗治下,国泰民安,八方来朝。前来朝廷的这些国家的使者,也在暗中较量,比较着进贡的宝物。起初,朝廷只提供存放贡品的地方,各国使节才能进入。这样一来,进贡的时候,就会发现有的包裹被偷偷调整过,有的甚至被偷走了。胆子大,居然有人敢在太岁头上破土动工。太宗大怒,于是“贡地”戒备森严。至于存放在这里的东西,有时候各国使节会做一些装修工作,无形中增加了皇城守卫的工作量。侍卫长上书建议,各国使臣的随身物品,全部放在“贡司”分配给他们的“小柜子”里。只有他们才能打开它。这个时候不需要有人看守,一切都井井有条。来自世界各地的使者的东西也丢失和错过了。大殿内进行了歌舞表演。太宗高兴地看着各国送来的珍宝,擦了擦嘴唇上的油说:这个“小柜子”果然不错。每年来拜访的使节,这个柜子一直为他保管着,他每年都会用到。每年来的新使者,他们的内阁应该怎么办?不用担心,寝具分配负责人会根据在任使节存放的物品,提供同规格的柜子。这里各国的使节都是在应用程序中向非线程安全的地方写入数据,就像我们的多线程一样,所以很容易出现数据混乱和丢失的情况。为了保证线程的执行安全,可以对方法进行加锁。但是,在重兵把守之后,所有传入的请求都需要排队执行,效率打了折扣。而上面提到的“小柜子”就是我们文章的主角:ThreadLocal。为每个不同的使者分配不同的机柜,使它们之间的数据隔离,互不影响。newcabinetallocation是ThreadLocal为新线程提供initValue的实现。在多线程应用环境中,为了防止多个线程之间的数据相互干扰,我们可以实现锁、栈闭包等,ThreadLocal也是其中之一。ThreadLocal类的名字很好听。顾名思义,local相当于一个线程的本地数据。这样每个线程的数据都保存在自己的本地,互不影响。回到代码,我们看看ThreadLocal是如何关联到各个Thread的?我们看,每个Thread都有这样一个属性,一个ThreadLocal.ThreadLocalMap属性,不能互相影响的秘诀就在这里。/*ThreadLocalvaluespertainingtothisthread.Thismapismaintained*bytheThreadLocalclass.*/ThreadLocal.ThreadLocalMapthreadLocals=null;这个ThreadLoalMap是什么时候设置的?下面看看ThreadLocal的使用。一般用法是:ThreadLocallocal=newThreadLocal(){protectedIntegerinitialValue(){return1;}};然后使用此ThreadLocal变量进行设置和获取操作。设置的时候会先判断当前线程是否分配了map,没有就创建。publicvoidset(Tvalue){Threadt=Thread.currentThread();ThreadLocalMapmap=getMap(t);if(map!=null)map.set(this,value);elsecreateMap(t,value);}地图是否已经allocated是ThreadLocalMapgetMap(Threadt){returnt.threadLocals;},根据当前线程的ThreadLocals属性判断,creatingMap时,会给当前线程的threadLocals赋值voidcreateMap(Threadt,TfirstValue){t.threadLocals=newThreadLocalMap(this,firstValue);这个ThreadLocalMap包含数组形式的多个条目。get的时候,如果没有数据,会根据上面的initValue方法创建一个新的return。这样,多个线程使用不同的东西。那么这里还有一点。对于不同的事物,可以通过泛型来区分ThreadLocal。当然,你也可以把它们放在一起放在一个大脑里,只是需要费一番功夫才能搞定。【本文为专栏作家“侯书城”原创稿件,转载请通过作者微信公众号“Tomcat物语”获得授权】点此查看本作者更多好文