ThreadLocal的用途
场景1中的工具类线程不安全。强调的是每个线程需要一个独享的对象,每个Thread内有自己的实例副本,不共享。一步步来
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都是保存在线程中的。
如果您发现该资源为电子书等存在侵权的资源或对该资源描述不正确等,可点击“私信”按钮向作者进行反馈;如作者无回复可进行平台仲裁,我们会在第一时间进行处理!
加入交流群
请使用微信扫一扫!