摘要:概念类用来存放线程的局部变量,每个线程都有自己的局部变量彼此之间不共享。返回当前线程的局部变量初始值。工作流程的时候我们可以看见是从中获取的,也就是说这些局部变量真正存储在中的时候从中获取到了,然后再从中获取。和都用于解决多线程并发访问。
【概念
ThreadLocal类用来存放线程的局部变量,每个线程都有自己的局部变量彼此之间不共享。TheadLocal
public T get():返回当前线程的局部变量。
protected T initValue():返回当前线程的局部变量初始值。默认情况下 initValue(), 返回 null 。线程在没有调用 set 之前,第一次调用 get 的时候, get 方法会默认去调用 initValue 这个方法。所以如果没有覆写这个方法,可能导致 get 返回的是 null 。当然如果调用过 set 就不会有这种情况了。
public void set(T value):设置当前线程的局部变量。
ThreadLocal是如何做到为每一个线程提供多带带的局部变量呢?实际上在ThreadLocal类中有一个Map缓存,用于存储每一个线程的局部变量。Map中元素的键为线程对象,而值对应线程的变量副本。
/** * Construct a new map initially containing (firstKey, firstValue). * ThreadLocalMaps are constructed lazily, so we only create * one when we have at least one entry to put in it. */ ThreadLocalMap(ThreadLocal> firstKey, Object firstValue) { table = new Entry[INITIAL_CAPACITY]; int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1); table[i] = new Entry(firstKey, firstValue); size = 1; setThreshold(INITIAL_CAPACITY); }【工作流程
1.set()的时候:
public void set(T value) { Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) map.set(this, value); else createMap(t, value); }
我们可以看见ThreadLocalMap是从currentThread中获取的,也就是说这些局部变量真正存储在currentThread中:
void createMap(Thread t, T firstValue) { t.threadLocals = new ThreadLocalMap(this, firstValue); }
2.get()的时候:
public T get() { Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) { ThreadLocalMap.Entry e = map.getEntry(this); if (e != null) { @SuppressWarnings("unchecked") T result = (T)e.value; return result; } } return setInitialValue(); }
从currentThread中获取到了ThreadLocalMap,然后再从中获取value。如果没有值,则调用setInitialValue()。
【如何使用package ThreadLocal; import java.util.Random; import static ThreadLocal.ThreadLocalTest.localSetter; /** * 在每个线程中多带带存放一个值然后再获取 */ public class ThreadLocalTest { static ThreadLocal localSetter = new ThreadLocal(); public static void main(String[] args) { for (int i = 0; i < 10; i++) { MyThread t = new MyThread(); t.start(); } } } class MyThread extends Thread{ private static Random random = new Random(); @Override public void run(){ //现在当前线程中存入一个随机变量 v1 int randomVar = random.nextInt(100); localSetter.set(randomVar); System.out.println(getName() + " random is " + randomVar); //获取当前线程的随机变量 v2 //v1 永远等于 v2 System.out.println(getName() + " localVar is " + localSetter.get()); } }【spring与ThreadLocal
spring中的bean大多都是单例的,但是我们应用又是支持并发的,所以将各个service,dao存放在ThreadLocal中是一个明智的做法。但是需要注意如果bean中包含共享变量,spring是没有做任何的安全处理的。
【synchronized与ThreadLocalThreadLocal以空间换取时间,提供了一种非常简便的多线程实现方式。
ThreadLocal和Synchonized都用于解决多线程并发访问。但是ThreadLocal与synchronized有本质的区别:
synchronized是利用锁的机制,使变量或代码块在某一时该只能被一个线程访问。而ThreadLocal为每一个线程都提供了变量的副本。Synchronized用于线程间的数据共享,而ThreadLocal则用于线程间的数据隔离。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/68300.html
摘要:相比与其他操作系统包括其他类系统有很多的优点,其中有一项就是,其上下文切换和模式切换的时间消耗非常少。因为多线程竞争锁时会引起上下文切换。减少线程的使用。很多编程语言中都有协程。所以如何避免死锁的产生,在我们使用并发编程时至关重要。 系列文章传送门: Java多线程学习(一)Java多线程入门 Java多线程学习(二)synchronized关键字(1) java多线程学习(二)syn...
摘要:因为多线程竞争锁时会引起上下文切换。减少线程的使用。举个例子如果说服务器的带宽只有,某个资源的下载速度是,系统启动个线程下载该资源并不会导致下载速度编程,所以在并发编程时,需要考虑这些资源的限制。 最近私下做一项目,一bug几日未解决,总惶恐。一日顿悟,bug不可怕,怕的是项目不存在bug,与其惧怕,何不与其刚正面。 系列文章传送门: Java多线程学习(一)Java多线程入门 Jav...
摘要:是的简称,运行环境,为的运行提供了所需的环境。分割字符串,返回分割后的字符串数组。当计算的值相同时,我们称之为冲突,的做法是用链表和红黑树存储相同的值的。迭代器取代了集合框架中的,迭代器允许调用者在迭代过程中移除元素。 Java基础1.JDK和JRE有什么区别? JDK 是java development kit的简称,java开发工具包,提供java的开发环境和运行环境。JRE 是j...
摘要:开始学习也有一段时间了,一些基础的书也扫了一遍了。最近慢慢开始看和,后者的话和有类似之处,都是一些编程经验的编程的世界里好多的东西都是相同的。这里其实是对的最佳实践,之后该对象已经变成一个过期的引用了,此时就应该清空这个引用。 开始学习java也有一段时间了,一些基础的书也扫了一遍了(think in java/core java volume 1)。最近慢慢开始看和,后者的话和有类似...
阅读 3247·2021-10-27 14:20
阅读 2527·2021-10-08 10:05
阅读 1627·2021-09-09 09:33
阅读 2905·2019-08-30 13:16
阅读 1437·2019-08-29 18:34
阅读 1173·2019-08-29 10:58
阅读 1230·2019-08-28 18:22
阅读 1228·2019-08-26 13:33