00:00
各位同学,接下来给大家介绍12LOCAL源码分析。好,通过前面的案例讲解和编码演示,我们应该结合阿里巴巴的开发手册,也知道了这个local在编码时候它相关常见常用的API和对应的编码规范,比如说什么时候用remove,对吧?那这些介绍完成以后。底层原理我们就有必要来了解一下,那对于th local的源码解读呢?最经典的就这道面试题,如果说你看过100%这三个会知道,那么就是thread thread local和thread local map,它们三者的关系好,那么先打开我们的API,我们会突然发现我们现在讲的是thread local,但是另外一个类叫thread,那说穿了就是一个叫thread线程类,一个叫thread local,线程局部变量是两个不同的类。由它作为我们的突破口来首先打开我们的现成类,好,同学们别眨眼,在这块你会大吃一惊,在我们thread.java这个里面。
01:07
居然有一个12的local OK,好,再点开来,同学们。Thread是一类thread local线程局部变量,好的,那这有空发现那就。顺藤摸瓜继续,这有read map thread local map。我再点,诶,并没有弹出第三个类。确实在。Static class静态内部类里面有个local map,他在哪里面,所以说我们会得到一个结论,他们三者。那么。线程类里面包含着thread local thread local这个类里面又有一个名叫thread local map的静态内部类,同学们,这三者的关系能不能跟上?
02:00
OK,这是第一个知识点,好,我们再捋一遍。来吧,先来看thread和thread local,那么前面我们是不是也说过,为什么thread local是现场安全的人手一份?各拿出自己的一份,不会冲突,何以见得,请大家看,当我们每拗一个线程的时候,是不是每个线程都有个local点2MAP这么一个field,这么一个实例变量类似于,所以说我们这儿就会得到再次体会一下。各自县程人手一份,不和别人共用。第一个问题,第二个local和local map,它们两者的关系呢?再点开。这个叫thad local,里面有个静态内部类叫thread local map,原来它们三者的关系是什么?是由两个类thread和thad local,然后我们说多线程里面的每个线程有一份,其实是每个线程有一份thad local,那么这个thad local里面实质而言它又是有一个local map,那么在这个里面请看代码。
03:11
有这么多,OK,整个一大坨而言,最关键的这我会引出来一个东西,叫静态的内部类entry。那么一说entry,我们是不是就会明白,类似于我们哈希map的K直队呀?好的,那么引出来这些以后初次体会,我们来看看它们三者的概括和关系来。打开脑图,我们可以看到现场类thread thread local map3个类。他们各自的关系如图所示,首先每个线程类thread.java对吧?这是一个常见的线程类,里面有一个属性叫thad local,对th local map,一看这个你也明白,实质上而言,它真真正正干活有用的是这个th local map,而它又来自于哪呢?Thad local map又嵌进去,是我们th local的一个静态内部类,OK,那么前面也强调过现程类,大家看又有一个属性。
04:13
叫local map,完整的是叫local这个类里面的一个静态内部类local map大家请看啊,我一点点进去,点进去以后一说map,自然而然,只要是加二成弦。情不自禁的就会想到哈希map,只要是哈希map就会想到K建支队,所以说我们就会明白,原来这个底层里面的静态的,内部类map里面也有个静态的。内部类entry,注意它继承了一个什么东东,这个是不是叫wake reference俗称,若引用啊,那么后面我们会说这有一道关键的面试题,为什么S里面。Map,它要继承了一个wake reference弱引用,那么学过Java虚拟机这门课的同学都会明白前、软弱、虚四大引用,OK,我们后面会说这个就非常重要,那么这个先暂时搁置,那么继续,我们会明白entry,大家请看,T就是local value就是我们传来的值,好。
05:20
那么这些是怎么来到的呢?我们呢,跟着源码走一遍。回到我们自己之前写的案例,我们现在呢,对于所local这个呢,说过了初始化,OK,那么来吧,就五个方法嘛,这个是初始化,这个是初始化remove。简单一删,重要的是不是就是get或者是that好。下面先说get。那么这样。也就是说这个线程我自己自己线程里面有个信息存在了一个叫start local里面先get,怎么get呀,来请看怎么玩的,人家先获得当前线程,这个T拿着当前线程去找。
06:01
这有个方法叫get map,点开看,请看是不是就是得到我们的这个线程里面的thread locals这么一个属性变量,一点开它实而言就是什么?就是我们的local里面的s local map,好,这是我们的第一步,那么得到我们的s local map简写为map,后面我都叫map了啊,那么看看这个map是否等于空,那么假设。这个map不等于,那么我们进来OK,那么然然后的话呢,我们来看看,如果不等于,那那么就是从这个map里面按照这个线程去得我们的N垂,如果得到N了,我们呢,从这个T里面得到我们的N垂1.value。把result返回去,OK,如果这个map等于,那我们会调用set initial value设置初始值,还记不记得我们一再的强调过,这个是返回子线程,局部变量单线程什么东东初始值?原来我们是不是说过,我们来看一下这个方法,请看它就告诉你设置初始值对吧?来。
07:11
如果你不设置初始值,默认返回一个什么是个,那所以我们在编代码的时候。杨哥给大家强调过,一定要在这儿return一个初始值,不管是什么,最好不要给他,那否则容易报空指针异常,OK,好,那么这个呢,就是我们的get,如get方法不map,如果不等于,那说明找到了返回值啊,否则的话呢,我们呢要设置初始值。OK,好。那么现在按照我们刚才所写的,那么这个map首次新建的时候就返回了一个初始值,对吧,我们这个初始值,那么现在获得假设啊,这个初始值初始化了以后,就是我们的这个value,好,那么现在在get也刚才也看到过了,我们搁到这我们呢就来看看啊,设置这个初始值以后,如果map不等于那。
08:03
那么直接set进去,但是否则的话呢,我们要干嘛创建一个map,那么这个map又是怎么创建的呢?那么来同学们,我们直接进过来。大家请看所谓的创建map,是不是也是我们我们这儿的这个线程的locals,实质而言就是拗了我们一个什么local map,这个first key first value,就是我们的当前线程和我们传进去的这个值啊。OK,来,笛子再进来,是不是拗了一个N垂,那么初始值是多少?16,那么是不是又跟我们的哈希map有异曲同工之妙啊,好吧,那么来,这个是我们的get,大致是这样,那么我们的sat呢,和之前的也一样,和刚才那个initial那个方法也差不多,不也就这么回事吗?如果不等于,那说明已经有了继续设置啊,OK,比如说又加了一次,或者又更改了一个值啊,如果没有的话,那么创建我们的map OK,所以说呢,我们呢,呃。
09:03
用初始化构造方法或者set都可以,里面有相应的判断,那么。来进行我们对应的create map这个方法。所以说回到我们的脑图笔记,我们就可以获得。你实上而言就是一个以10LOCAL实例为key,任意对象为value的一个什么ENT垂对象来,ENT垂对象实质而言就是一个TV建制,对对吧,Set进去就是一个key和一个value来。那么当我们以s local。当我们为这个local变量赋值的时候,OK,实际上就是以当前local的实例为K值为value,往这个map里面去存放,OK,那么这个就是他们三者相关的一个关系,好。那假设啊,各位同学,你要是觉得你在这儿还是有点吃力,不懂的话,那么杨哥能不能用一句话给我讲明白来?
10:01
我们搁到这儿啊,我让大家好看,这个我相信大家呢,没有任何的问题了,这三个类都看了源码了,一句话给大家讲明白它们三者的关系。就是一个三角形。来,那么现在。就三句话。第一句话。这是一个类。县城内,那么假设我们举个最经典的case啊,就是我们的自然人。OK,好,那么请问。每个人都需要有信息来标注,最经典的是不是我们的什么身份证,那么现在有两个独立的类,一个叫TH的Java现场,你可以把它看作就是每一个人,每一个自然人,每一位同学,每一个人是不是应该身上钱包里面,或者怎么着是有那一张聚指塑胶所做的一张身份证,那张卡片,那么现在thad local就是我们的什么?
11:00
身份证卡片。本身那么就是卡片,OK,那么它。就是我们的ER。我相信同学们。大家呢?也能接受,也能理解吧,好,理解吧,好。一个人拿着这张卡片。县城拿这张卡片看什么呀?要看我们的上面的身份证的信息,那么这个身份证的信息内容就是这个是吗?信息内容。那么。就是身份证和我们的名字。我们这样的一对。TV。建职队,你就可以把它当做就是我们的thread local map OK,讲完了,说穿了就是这个人我需要有。比如说我现在去。汉庭酒店去入住,那么汉庭酒店一定要让我出示身份证信息,它主要看什么呀?主要看的是不是就是名字和身份证号,那么名字和身份证号是不是就是我这个人的一个KV建制队,好,那么这个KV建制队这个信息印在哪儿啊?那么是不是嵌在th local这张身份证卡片上面,所以说我们需要一个人的信息,每个人都人手都有一份身份证,听说过身份证上面需要跟别人抢的嘛,不用嘛,只代表你自己,你自己用对不对,那么所以说每个人有一张卡片人和卡片,这个卡片上面就印着你的身份证信息,就是个th local map,因为身份证信息。
12:37
最主要的也就是你的个人的名字和你的身份证号类似一个兼职队,这个就是他们三者的关系,那么我相信讲到这同学们应该是可以搞定对吧?所以说呢,明白这三者就是人身份证卡片和卡片上面的信息,这个KV建设队以后,我们最后来做个小总结。近似的啊。
13:01
可以理解为local map,字面上也可以看出是个保存所对象的一个map key嘛,就是我们的所local,它只不过是经过了两层包装的一个local对现什么叫两层呢?Thread,我要拿到这个map就是thread local,说穿了就是什么thread local map,而thread local map是第一层包装,第二层包装又是一个什么N垂建之队。好,那么再回顾刚才我们的案例,这个人。人最重要的身份证信息名字啊,身份证号保存在哪呢?保存在我们的local身份证上面,印在这个身份证上面,这张塑料卡片上面,人卡片,卡片上面有信息,OK,好,那么所以说Java虚拟机内部就维护了一个现成版的map,也就是我们的STEM map,这个map一个个的建值队叫entry,这个建值队key叫local value就是我们的存进去的这个对象,那么通过我们set对象丢进去的,那么说穿了就是自己,那么身份证上面的信息是要印在这张卡片上面,卡片上面有信息,信息印在卡片上面,他们两个要local s local map的关系,那么所以说s local对象当做key放进到我们这个local map当中,每个线程要用到这个线程的时候,就拿当前的线程去map里面去获取,大家请看我们在获取get的时候,是不是有一个东西叫get map,当前线程这个T如果说能够。
14:28
获得了,那么就是不等于,那那么是什么?就是返回,否则的话你该初始化,初始化或者做进一步的设置,那么这样通过每个线程让都让自己都拥有了自己独立的一个变量,人手一份,竞争的条件被彻底消除,所以说在并发模式下绝对安全,因为一个人一个身份证,我拿别人的也没用,对不对,别人也不会来跟我抢,所以说人手一份最安全。th local local map,他们三者的关系就如我们刚才所讲的身份证这个案例请大家务必了解。
我来说两句