多线程(十七):ThreadLocal原理


prtyaa
prtyaa 2023-12-28 16:51:07 49733 赞同 0 反对 0
分类: 资源
多线程访问共享可变数据时,涉及到线程数据同步的问题

ThreadLocal的用途

场景1中的工具类线程不安全。强调的是每个线程需要一个独享的对象,每个Thread内有自己的实例副本,不共享。一步步来

注意,看上图代码,每个线程都调用了dates()创建了SimpleDateFormat对象。

10个线程的话,我们写for循环。

线程池效率很高,速度也快。

缺点是:有10个线程,有1000个任务,每个线程执行100个任务,每个任务里都调用了dates()方法创建了SimpleDateFormat对象,也就有1000个SimpleDateFormat对象。

那怎么办?我们可以把SimpleDateFormat对象提出来成静态属性,不就行了?来看代码

抽出来作为全局静态字段的问题就是会出现重复的时间,原因就是:

所有的线程都指向了一个同一个SimpleDateFormat静态对象,而这个静态对象本身是线程不安全的。


那怎么办? 加锁呗,来看看:

这种方式保证了数据的安全(没有重复时间,放进了set集合里,set的容量是1000,for循环1000,所以没有重复),但是每一次都要加锁解锁,效率很低。


ThreadLocal的另一个使用场景

第一个request请求进来,给threadlocal里设置一个user1, 这个线程所在的任何方法,service2,service3 都可以拿到所设置的对象。

而第二个request请求进来,也可以给threadlocal里设置一个user2, 这个线程所在的任何方法,service2,service3 也都可以拿到所设置的对象。而且第一个请求线程拿不到user2,第二个请求线程拿不到user1。 互相是分开的独立的。

ThreadLocal的两个作用:

1、让某个需要用到的对象在线程间隔离,即:每个线程都有自己的独立的对象

2、在任何方法中都可以轻松获取到该对象

而每一个ThreadLocalMap里面有很多个ThreadLocal 。看下面的代码:

在拿User对象的ThreadLocal的同时,也可以拿到SimpleDateFormat的ThreadLocal,一个线程中完全有可能用两个ThreadLocal。


然后我们再看一下ThreadLocal的get方法:

 

首先拿到当前线程,然后去getMap里去查 线程里有没有threadLocals,如果map为空的话,那么就直接走setInitiaValue()方法

这个方法第一句就是去取initiaValue方法的值,也就是我们重写的那个被保护的方法,再上面的SimpleDateFormat实例中是这个:

也就是说get方法,进来如果map里取不到值,那就直接取我们设置的initiaValue()方法里的值。

如果之前set过,看上图的代码,那么就说名map里有值,然后get的时候,就会进入下图这个红框,而不会去initiaValue()方法里去取值了。

Thread类中 有ThreadLocalMap之前也说过了。所以map的key,value都是保存在线程中的。

如果您发现该资源为电子书等存在侵权的资源或对该资源描述不正确等,可点击“私信”按钮向作者进行反馈;如作者无回复可进行平台仲裁,我们会在第一时间进行处理!

评价 0 条
prtyaaL2
粉丝 1 资源 1949 + 关注 私信
最近热门资源
银河麒麟桌面操作系统备份用户数据  130
统信桌面专业版【全盘安装UOS系统】介绍  128
银河麒麟桌面操作系统安装佳能打印机驱动方法  120
银河麒麟桌面操作系统 V10-SP1用户密码修改  108
麒麟系统连接打印机常见问题及解决方法  27
最近下载排行榜
银河麒麟桌面操作系统备份用户数据 0
统信桌面专业版【全盘安装UOS系统】介绍 0
银河麒麟桌面操作系统安装佳能打印机驱动方法 0
银河麒麟桌面操作系统 V10-SP1用户密码修改 0
麒麟系统连接打印机常见问题及解决方法 0
作者收入月榜
1

prtyaa 收益393.62元

2

zlj141319 收益218元

3

1843880570 收益214.2元

4

IT-feng 收益210.13元

5

风晓 收益208.24元

6

777 收益172.71元

7

Fhawking 收益106.6元

8

信创来了 收益105.84元

9

克里斯蒂亚诺诺 收益91.08元

10

技术-小陈 收益79.5元

请使用微信扫码

加入交流群

请使用微信扫一扫!