深入浅出 ThreadLocal 面试问题:
1. ThreadLocal的实现原理是什么
2.如何使用ThreadLocal?
3.ThreadLocal是用来解决什么问题的?
概述:ThreadLocal是线程局部变量,每个线程都持有一个这样的副本,每个副本可以独立操作get(),set(), remove() ,并且与其他线程隔离。
问题一:ThreadLocal的实现原理是什么:
Thead->ThreadLoaclMap->Entry[]->key(ThreadLocal) value-set()
每个Thread都有一个ThreadLocalmap,每当创建一个ThreadLocal,将ThreadLocal为实例对象存入map的Key值中,取出的方法也是一样。
问题二:如何使用ThreadLocal
set()方法:当调用set()方法,线程先会去查看map是否为空,如果为空就creatmap(),否则就将值放入map-ThreadLocal作为key,value为设置的值
get()方法:当调用get()方法时,获得当前线程副本的值,如果map不为空,获得entry[]然后取得value, 如果为空,调用setinitialvalue()方法设置初始值
问题三:ThreadLocal是用来解决什么问题的
- 线程级别的变量传递,ThreadLocal作为线程的局部变量,这也就能实现
- 线程不安全问题:ThreadLocal作为线程局部变量,为我们带了并发编程带来了一个新的思想-避免并发,如果当一个对象自己是线程不安全的,但是你想并发访问,这就可以用到ThreadLocal
- case1:SimpleDateFormat:
public class TestDemo6 {
private static ThreadLocal<SimpleDateFormat> threadLocal = new ThreadLocal(){
@Override
protected SimpleDateFormat initialValue() {
System.out.println("执行了初始化方法");
return new SimpleDateFormat("mm:ss");
}
};
public static void main(String[] args) {
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(10,10,0, TimeUnit.SECONDS,
new LinkedBlockingQueue<>(1000));
for (int i = 0; i < 1000; i++) {
int I= i;
threadPoolExecutor.submit(new Runnable() {
@Override
public void run() {
Date date = new Date(I*1000);
MyFormat(date);
}
});
}
}
private static void MyFormat(Date date) {
String time = threadLocal.get().format(date);
System.out.println(date);
}
}
在这里SimpleDateFormat每个线程只需要初始化一次,解决了线程不安全问题,同时优化。``