大话ThreadLocal

开发 开发工具
在多线程的应用环境中,为了多个线程间的数据互不影响,我们可以通过加锁,栈封闭等多种方式来实现, ThreadLocal也是一种。

话说大唐贞观年间,物华天宝,人杰地灵。太宗治下国家一派祥和,四方来朝。

这些各国前来朝见的使臣,也在暗中较量,比较进贡宝贝。一开始朝中只提供了一个存放贡品,各国使臣都可以进入。这样一来在贡品呈现时会发现有些已经被偷偷调了包,甚至有些被偷走了。

大胆,竟然有人敢在太岁头上动土。太宗震怒,于是「贡品处」被重兵把守。而这里存的东西,有时各国使臣还会做些修饰工作,无形中加大了皇城守卫的工作量。守卫统领上书建议,将各国使臣的物品,都放在「贡品处」为他们自己分配的「小柜子」里。只有他们自己可以打开。

这时不需要人把守,也都井然有序。四方使者的东西也没正丢失弄错过。

大殿里歌舞表演ing,太宗高兴地看着各国送来的宝贝,擦了一把嘴边的油说:

这「小柜子」真是好呀。对于每年都来朝见的使者,这个柜子一直给他留着,每年来都用啊。

对于每年新来的使者,他们的柜子怎么办呢?放心好了,负责被褥发放的会根据当前使者存放物品提供一个等规格的柜子。

这里各国使臣就像我们多线程一样,都在向应用中非线程安全的一个地方写数据,因此很容易出现数据错乱、丢失等情况。

为了保证线程的执行安全,可以为方法进行加锁。但重兵把守后,所有来的请求都需要进行排队执行,效率上打了折扣。

而上面说的「小柜子」,就是我们本文的主角:ThreadLocal。对于每个不同的使者,分配的是不同的柜子,这样他们之间的数据就被隔离开来,互不影响。

[[225270]]

新的柜子分配就是 ThreadLocal对于一个新线程提供initValue的实现。

在多线程的应用环境中,为了多个线程间的数据互不影响,我们可以通过加锁,栈封闭等多种方式来实现, ThreadLocal也是一种。

ThreadLocal 这个类的名称起的很好,类如其名,local,相当于是一个线程的本地数据,这样每个线程的数据都存在自己的local里,互不影响,各自占山为王

也是逍遥自在。

回到代码,我们来看 ThreadLocal 是如何和各个 Thread 之间建立起关联的呢?

我们来看,每个Thread,都有这样一个属性,一个ThreadLocal.ThreadLocalMap的属性,能互不影响的秘密都在这里。

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

这个ThreadLoalMap是什么时候被设置值的呢?

我们来看ThreadLocal的使用。

一般的用法是:

  1. ThreadLocal<Integer> local = new ThreadLocal<Integer>() { 
  2. protected Integer initialValue() { 
  3.                     return 1; 
  4.                 } 
  5. }; 

然后使用这个ThreadLocal变量进行set和get操作。

set的时候,会先判断对于当前线程,是否已经分配了map,没有则创建。

  1. public void set(T value) { 
  2.         Thread t = Thread.currentThread(); 
  3.         ThreadLocalMap map = getMap(t); 
  4.         if (map != null) 
  5.             map.set(this, value); 
  6.         else 
  7.             createMap(t, value); 
  8.     } 

是否已经分配过map就是根据当前线程的 theThreadLocals 属性来判断的

  1. ThreadLocalMap getMap(Thread t) { 
  2.     return t.threadLocals; 

那createMap的时候,就会给当前线程的threadLocals赋值

  1. void createMap(Thread t, T firstValue) { 
  2.     t.threadLocals = new ThreadLocalMap(this, firstValue); 

这个ThreadLocalMap里是以数组的形式放的多个Entry。

在 get 的时候,如果没数据会根据上面的initValue方法创建一个新的返回。这样多个线程用的就是不同的东西了。

那这里还有一点,对于不同的东西, ThreadLocal 可以通过泛型做区分,当然你也能一股脑的放到一起,那取的时候就费劲了。

【本文为51CTO专栏作者“侯树成”的原创稿件,转载请通过作者微信公众号『Tomcat那些事儿』获取授权】

戳这里,看该作者更多好文

责任编辑:赵宁宁 来源: 51CTO专栏
相关推荐

2009-06-02 16:58:56

运维管理配置摩卡

2011-07-14 13:50:09

ThreadLocal

2009-09-29 17:11:23

Hibernate T

2011-12-02 08:51:19

PHP

2017-02-14 08:36:56

2021-01-19 05:24:36

ThreadLocal线程编程

2015-09-09 08:45:49

JavaThreadLocal

2023-10-07 08:26:40

多线程数据传递数据共享

2016-11-01 19:22:36

Javascript前端Promise

2012-09-10 15:57:58

云计算混合云私有云

2022-05-11 07:36:12

Java线程安全

2021-05-06 08:55:24

ThreadLocal多线程多线程并发安全

2023-08-02 08:54:58

Java弱引用链表

2011-12-19 14:28:14

2012-08-22 13:53:15

Windows 8Linux

2013-11-26 15:44:25

2015-11-12 10:09:47

2011-07-14 14:15:40

ThreadLocal

2023-11-02 08:27:29

2022-05-14 21:19:22

ThreadLocaJDKsynchroniz
点赞
收藏

51CTO技术栈公众号