本文主要是对上篇中ThreadLocal进行一个小讲解https://blog.csdn.net/qq_38340127/article/details/109866392,若有错误希望观众老爷们帮忙指出下,我好改进谢谢。
目录
四、 SimpleDateFormat线程不安全如果使用不当会怎么样
一、ThreadLocal的作用
在源码中有一段这样的注释:
* This class provides thread-local variables. These variables differ from
* their normal counterparts in that each thread that accesses one (via its
* {@code get} or {@code set} method) has its own, independently initialized
* copy of the variable. {@code ThreadLocal} instances are typically private
* static fields in classes that wish to associate state with a thread (e.g.,
* a user ID or Transaction ID).
翻译一下就是
*此类提供线程局部变量。这些变量不同于
*它们的正常对应关系是每个线程访问一个线程(通过
*{@code get}或{@code set}方法)有自己的独立初始化
*变量的副本。{@code ThreadLocal}实例通常是私有的
*类中希望将状态与线程关联的静态字段(例如。,
*用户ID或事务ID)。
* <p>Each thread holds an implicit reference to its copy of a thread-local
* variable as long as the thread is alive and the {@code ThreadLocal}
* instance is accessible; after a thread goes away, all of its copies of
* thread-local instances are subject to garbage collection (unless other
* references to these copies exist).
*<p>每个线程都有一个对其本地线程副本的隐式引用
*变量,只要线程是活动的并且{@code ThreadLocal}
*实例是可访问的;在线程离开后,它的所有副本
*线程本地实例要进行垃圾回收(除非
*存在对这些副本的引用)。
具体的总结下就算是,提供线程局部变量,具体就是首先通过set,然后再通过get,这样就可以获取到之前设置到线程中的值了。那么我们就用代码来测试下:
import java.text.SimpleDateFormat;
import java.util.Date;
public class Test {
public static void main(String[] args) {
final ThreadLocal<SimpleDateFormat> threadLocal = new ThreadLocal<SimpleDateFormat>();
threadLocal.set(new SimpleDateFormat("HH:mm"));
SimpleDateFormat tmp = threadLocal.get();
Date now = new Date();
String value = tmp.format(now);
System.out.println(value);
// 新线程中获取对应的SimpleDateFormat
new Thread(new Runnable(){
public void run() {
SimpleDateFormat tmp = threadLocal.get();
System.out.println(tmp);
}
}).start();
}
}
上面的结果如果根据注释来的话,新线程里面的SimpleDateFormat获取到的应该是null,那么具体是这样么?
最终输出结果
22:18
null
结果和注释一毛一样,那么他是how to do it?????
具体查看下set方法:
// 这块就是ThreadLocal所调用的set方法
public void set(T value) {
// 获取当前线程
Thread t = Thread.currentThread();
// 根据当前线程获取对应的ThreadLocalMap
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
// 看完代码应该就是对应的ThreadLocalMap 其作用咯?具体查看下getMap方法
ThreadLocalMap getMap(Thread t) {
// 意思就是说ThreadLocalMap其实就是线程的一个变量0 0原来如此
return t.threadLocals;
}
// 通过Thread中的源码我们就能看到原来是有这么一个值,放在那里
ThreadLocal.ThreadLocalMap threadLocals = null;
//可是Thred代码下一行还有一个,这个又是干啥的?具体可以后续在讨论
ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;
那么根据这个意思就是获取当前线程,然后往这个线程里塞个变量,这个变量是通过Map形式进行key(而这个key就是对应的ThreadLocal),value存储的,下次获取的时候根据这个ThreadLocal就能拿到value了。
//如果map存在直接放进去
private void set(ThreadLocal<?> key, Object value) {