登陆

BAT面试必考:ThreadLocal,ThreadLocalMap 和Thread 的联系

admin 2020-02-14 190人围观 ,发现0个评论

MySQL温习:20道常见面试题(含答案)+21条MySQL功用调优经历

01 导言

这三种的联系由于很多的内部类的联系,第一次看的时分仍是有点绕的,感觉你是老子的孙子,又是老子的老子。我仍是主张你先抛开内部类的联系,把每一个类当作一般类来看到,了解每個类的责任,最终再把内部类放进去考虑这样规划BAT面试必考:ThreadLocal,ThreadLocalMap 和Thread 的联系的意图。这儿也给咱们一个启示,面临杂乱的工作的时分,咱们需求跳出来,先把问题简略化,大方向掌握了,再进一步去细化每一个功用点和规划的艺术。

02 联系图解

接下来咱们看下面一张图

从上图咱们能够发现Thread 中持有一个ThreadLocalMap ,这儿你能够简略了解为便是持有一个数组,这个数组是Entry 类型的。 Entry 的key 是ThreadLocal 类型的,value 是ObjectBAT面试必考:ThreadLocal,ThreadLocalMap 和Thread 的联系 类型。也便是一个ThreadLocalMap 能够持有多个ThreadLocal。他们是一对多的联系(当然Entry 还涉及到弱引证的技能,这儿不打开,否则就没完没了了)加上内部类的联系

03 为什么ThreadLocalMap 规划为ThreadLocal 内部类

看到各种内部类是不是有点晕,感觉你是老子的孙子,又是老子的老子,为什么不独立ThreadLocalMap 出来呢?其实这儿涉及到内部类起到封装的效果。来,咱们看看源码的解析

/**

* ThreadLocalMap is a customized hash map suitable only for

* maintaining thread local values. No operations are exported

* outside of the ThreadLocal class. The class is package private to

* allow declaration of fields in class Thread. To help deal with

* very large and long-lived usages, the hash table entries use

* WeakReferences for keys. However, since refereBAT面试必考:ThreadLocal,ThreadLocalMap 和Thread 的联系nce queues are not

* used, stale entries are guaranteed to be removed only when

* the table starts running out of space.

*/

static class ThreadLocalMap {

//这儿省掉其他特点和办法

}

主要是阐明ThreadLocalMap 是一个线程本地的值,它所有的办法都是private 的,也就意味着除了ThreadLocal 这个类,其他类是不能操作ThreadLocalMap 中的任何办法的,这样就能够对其他类是通明的。一起这个类的权限是包等级的,也就意味着只要同一个包下面的类才干引证ThreadLocalMap 这个类,这也是Thread 为什么能够引证ThreadLocalMap 的原因,由于他们在同一个包下面。

尽管Thread 能够引证ThreadLocalMap,可是不能调用任何ThreadLocalMap 中的办法。这也便是咱们平常都是经过ThreadLocal 来获取值和设置值,看下以下代码

public class Test {
public static void main(String[] args) {
ThreadLocal local = new ThreadLocal<>();
local.set("hello word");
System.out.println(local.get());
}
}

但咱们调用ThreadLocal 的get 办法的时分,其实咱们最终是经过调用ThreadLdocalMap 来获取值的

 public T get() {
//这儿经过获取当时的线程
Thread t = Thread.currentThread();
//经过线程来获取ThreadLocalMap ,还记得咱们上面说的Thread 里边有一个ThreadLocalMap 特点吗?便是这儿用上了
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();
}
ThreadLocalMap getMap(Thread t) {
return t.threadLocals;
}

到这儿,读者应该大约理解了,其实ThreadLdocalMap 对运用者来说是通明的,能够当作空气,咱们一值运用的都是ThreadLocal,这样的规划在运用的时分就显得简略,然后封装性又特别好。

04 ThreadLdocalMap 什么时分开端和Thread 进行绑定的呢

在第一次调用ThreadLocal set() 办法的时分开端绑定的,来咱们看下set 办法的源码

 public void set(T value) {
Thread t = Thread.curren我们仨tThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
//第一次的时分进来这儿,由于ThreadLocalMap 还没和Thread 绑定
createMap(t, value);
}

//这个时分开端创立一个新的ThreadLocalMap 赋值给Thread 进行绑定
void createMap(Thread t, T firstValue) {
BAT面试必考:ThreadLocal,ThreadLocalMap 和Thread 的联系t.threadLocals = new ThreadLocalMap(this, firstValue);
}

还有更多面试真题题共享如下,转发+私信关键词【材料】即可免费收取~

请关注微信公众号
微信二维码
不容错过
Powered By Z-BlogPHP