马士兵-MCA-架构师课程笔记-四-

马士兵 MCA 架构师课程笔记(四)

系列 3:P66:【Spring】SpringMvc的扩展 - 马士兵_马小雨 - BV1zh411H79h

下面再来介绍第三个点叫mc的一个扩展内容是啥意思啊,什么叫spring mc的扩展,这块也一样,我从官网里面截取的某一部分东西来找找一个spring mvc的一个扩展,哪去了诶,走掉了。

希望老师不要劝退啊,不会的不会的,原码没那么难,没那么难好吧,别别想太多,然后来看看这块的一个最基本解释,说cbot提供了适用于大多数spring vc应用的一个自动配置,第一个叫contest。

什么东西是一对be,你看到这些病之后叫will reserver,好吧,will reserve是干嘛的,这叫视图解析器啊,你们都学过mvc了吧,有不会mvc的吗,不会的同学扣二有不会的吗,小虎不会啊。

不可能吧,不过没关系好吧,你知道里面有什么东西叫视图解析器,这不是看到了,是不是里面自己经加载的,第二个什么叫支持服务,静态资源,刚刚已经看到了,web站是可以的,第三个叫什么呢。

叫自动注册converter啊,converter和former什么意思,是不是指的我们的转换器和我们对应的一个格式化器,这个转换器是什么意思啊,你前端输入的项目输入的信息都是我们的字符串。

它能把对对应转换成对应一个实体类对吧,格式化什么意思,比如日期转成对应的一个格式,是不是都有,再比如说支持什么呢,也是computer是还有个叫message code reserver啊,这个东西啊。

一一般在那个to message这块,主要是在我们那个那个叫什么呃,国际化的时候可能会用一下好吧,一带四tml是吧,支持自定义的一个标签吧,还有什么东西叫confederation。

是不是也是一对bec初始化,所以这块是spring boot里面自动装载的一些配置啊,这我都做了解释,每个属性什么意思好,什么意思啊,看错了,第一个叫石头解析器对吧,然后第二个叫支引入静态资源。

现在的主动著作converter这些东西,然后这是我们的htp t a a t p请求和响应的一个转换,这是我们的错误代码生成规则,这是静态的一代词自定义的分呃,这个呃标标签不是标签那个那个图标。

再看看自动使用我们这样的东西,将请求数绑定到我们的java并中,是有很多这样的一个知识对吧,大家注意啊,这是谁,这是我们对应的那个bot里面自动集成的啊,自动提升之后往上看书。

自动配置的vs reserver,之后就是我们之前自己学的marvc的一个视图联系,并且根据方法的返回值取得试图对象,然后呢由视图对象决定如何进行一个渲染,就是我们的重立项和转发站功能这块也是一样的。

你看干嘛,你可以在我们对应的一个类里面进行一个查找,简单找对应类好吧,还是那样找里面的类,找哪一类,官网里面给我们表示出来一个类叫什么,叫它看看,把那y之后,我们去里面进行一个搜索。

怎么搜啊,是不是这个页面ctrl f ctrl v找这个吗,走往下走,往上看,这是东西,是不是告诉你说这个值是这样的一个值,这是不是引入进来了,引入进来之后。

下面告诉你说我这是一个will reserver,表示一个视图解析器,当前这个视图解析器,然后呢new了这样一个对象,你完对象之后往里边设置了一些相关的一些属性,是不是就能看到这个对线到对应相关信息了。

这是我们整体那个视图处理器的一个处理过程,是不是在我们的mv c呃,y版mvc auto configuration这个类里面,你能看到这个信息吧对吧,但是我也说过了。

这块不是说你随便写完之后就一定能生效,这是不是有很多判断叫conditional on be conditional on missing beans,是有很多的一些肯定判断。

你只有符合了对应的一个条件之后,这块才会生效,如果你没有对应条件的话,这块是不会进行一个生效的,你懂我意思吧。

ok掀开之后往下翻,这是不是只要有这样的一个具体类,这类完了之后你可以干嘛,看一下刚刚写好的具体的那个类表示什么意思,就说把类点开。

点完之后它是集成了继承什么东西,然后呢实现了什么样的东西,里面就告诉你说这就是一个最基本的视图解析器,tap那里面是不是定义了n多方法,但现在你看到这方法之后可能还有点懵啊,不知道是干嘛的啊。

不知道干嘛的,没关系,我这里面写了,看里面有一个方法叫什么呢,叫resolve,will name,要处理我们当前这个视图解析器的一个名称吧,是处理器的解析的名称对吧,处理名称的时候怎么处理的。

来我们看一下这方法刚刚已经翻到了啊。

那是哎干什么,看看是不是叫reserve,然后呢叫view name,老师spring版本boss版本多少,最新的2。2。2,最新的版本我们直接看最新的不看老了好吧,这是截出来一堆的一些请求集。

合完之后这种东西马上翻,这是一个if的判断,判断完了之后做些什么事情,看这看这行代码叫get啊,不会读啊,什么什么will,是不是,这样的获取方法,这方法返回什么,返回是一个list的一个will。

是返回是一个will的一个集合了,你点开当前这个方法好吧,这里面是不是告诉你说我要循环变量的集合了,集合循环变量的时候,是不是有for循环球员告诉你说我要处理当前这个视图解析器了,然后呢这有一个判断。

判断完了之后也是一个循环遍历的过程,便利之后把这个视图解析器都给拿出来,是不是这样的过程啊,所以你看了源码之后,你会发现说ok这里面有关于我们的视图解析器,完整的一个整体处理环节,一模块怎么找的。

我是怎么找到这个地方的,找完之后我是做哪些的一个处理,是不是经过自己一个旋火循环,我现在只是带你看一个大概的一个步骤,还有大概步骤之后讲袁老的时候,这块我们详细讲的,我会想一想,他这块你先别管。

你要知道说我一步步是怎么找进来的。

怎么来处理我们对应的一个视图就够了好,所以这里面我把代码给粘出来了,装完站出来之后,这个get什么vo,然后往里面进行一个旋转好吧,转完之后可以it这个sorry con,干什么东西把它给取出来。

所以他说了一句话,说通过上面代码的分析,我们知道了spring board是在容器中去查找视图解析器,因此我们可以干嘛,可以给容器自定义添加食肉,什么叫食肉啊,点视图啊,自己写啊,自己写的错别字啊。

是看了可以给容器自动添加,我们是不解气,这个时候这个类会帮我们将它给组合起来,是不是这意思啊,好吧,这块也一样,刚刚代码你告诉你说我把它加载到一个容器里面了,通过当前这个容器。

我们就能把我们的视图给取出来,它取出来之后,这可能是一个原理,再记住了啊,说它是在容器里面找,所以此时如果自定义了一个视图解析器,只需要把它声明为一个视图,我们意味着是就能自己做一个操作了,好在这。

我来看我这写个这样的东西啊,写什么写,他说了他这个will reserver,然后呢,mary reserver,然后写了这样一个缩写是吧,是不是自己定义的东西啊,不对啊,这下面下面是自定义东西。

叫py class,my view reserver in lee,什么东西,实验完之后什么处理都不做,不漏水之后,这可以return一个my will reserver,是不是这里写了一个be。

当你想到变之后,意味着我加载到我们当前容器里面了,此时你当前这个视图解析器就生效了,当然一般情况下你不需要做这件事,情,是不需要做这件事情,为什么,因为词汇vc里面它本身提供了收集器。

除非说它提供了收集器,不再满足你的需求了,你这个时候没办法,我必须要进行一个自定义了,基于这样的情况下,你猜怎么样呢,需要自己来完成一个添加过程,这块能听明白吗,能听明白吗,源码没带,你拿个看啊。

我这给你们截出来了,我说了源码,我们现在先不看看,先讲这些基础知识,先把这块东西搞明白了之后,我们再看源码好吧,这两把下来之后,有兴趣的同学你可以先看看,你可以先看看好吧。

每一步我给你写都其实有有能写注释的地方给你写注释了,来这里吗,能听到同学扣个一本来,是不是懵了,能听懂吗,摸摸满引擎是不是得重启,不需要他本身是不是支持了自己的公关引擎。

你知你除非用一个自己特定的荧光引擎啊,一般不需要是比如说你现在只需要处理一个视图解析器,就是说如果你现在想添加视图解析器的时候,为什么我把它声明成一个病,它能处理的就在刚刚代码里面。

你看到了它是从容器里面进行加载的时间有限,只有原版课的时候,我会详细带你们读里面每一个步骤到底干什么事情好吧,怎么做这样一个处理环节,这块我会带你们说的明白了吧,ok如果你这块看明白之后也一样。

回到我们这个官网这个环节,官网这块就刚刚说这块好吧,怎么进行添加的,你配置什么东西就行了,听到辉煌每一步步记录下来,没关系,我笔记会发出去,你按照我笔记里面写就行了,我这笔记啊写的比较详细的。

每一个步骤通过哪个类哪个方法找进来的,怎么都要调调,调过来的都写得比较清楚好吧,来再来看下面这块的一个文字描述,这个描分析描述我注意的是我们对应的官网里面的一个描述,他说了。

如果你想保留spring boot mvc的功能,并且需要添加其他mvc的一个配置,比如拦截器,比如格式化器,比如视图控制器,可以添加自己的web mvc,configuration。

debt内容的and configuration类,但是不能带上enable web mvc这个标签,为什么,因为你带上这个标签之后,就意味着你自己完全掌控了我们的mvc,而spring boot好吧。

就不再起作用了,虽然说了,如果你想自定义它它它这些实例好吧,可以声明一个y版mc registration or类来提供这些组件啊,刚才说了叫原油配置都失效,确实这样的,所以这可能会成为一个问题。

公告里面是不是四词都写的很清楚了,就是告诉你说一般不要做这件事,那我们这儿其实也可以做这样一个类似的配置,怎么配置呢,还有笔记里面写的,这样我自定义好自己的一类,记住你要继承这个时间类好吧。

一定要记住这个时间类好,接下来之后我们可以添加我们的视图控制器,来写一下吧。

打开我们的项目,找到我们的com mv,在里面,我有一个,package,再写一个咖啡的,这写一个class叫麦,config写完之后注意了,这一定要实现一个东西。

实现叫bb mvc configure,生完成之后在里面加一个方法叫i will control,当你加完函数之后,你发现它里面有个什么参数啊,叫registry吧,是不是注册的意思是registry。

a的什么东西,这个方法是不是i的vo control对吧,是不是vctrl,这里面你可以写什么,写一个随便的请求,它是ur地址嘛,有写一个叫m s b,然后呢这边写一个叫set,没有内功,这写些东西。

我们有页面吗,没任何页面是吧,创建页面吧,创建页面切换页面,这是一个hello,你好,老师就是老板了,这是一个hello,12o,虽然不懂是不是这完成这样的一个页面了,然后此时我后面给你写什么了。

写上我们对应的一个情节叫杠嗯,hello,第二htm呃,刚好了,是不是发生这样一个请求,当你写完这个请求之后,下面一个告诉我再怎么解,我需不需要在我们对应的一个control里面。

大家看到我说写这样的东西是不是返回一个词size。

你随便换个名字就行了,这个名字无所谓,当你匹配请求之后,我需不需要在我们当前这个control里面加一个。

看这这这这是一个lo,这访问是不是字符串,我们这rise control的,大家告诉我,你现在这样写有问题没有,我现在这样写的话,能进入到我们的同页面吗,能不能请求到来,重启下试试好吧,重下试试。

不行来把进攻掉。

进攻到这来请求一下试试,我才没叫过来,mf b告诉你什么。

这怎么做是吧,at confusion,ok别忘了这东西,at configuration刚刚在这儿说写的比较清楚了。

官网里面看这块说告诉你说你要添加一个哪儿哪去了,and configuration类,必须要把它做一个标识吧,是不是必须要把它做一个标识,是不是写了,但是你不要带这个标签,不要带这个标签。

这个标签之后可能会成为一个问题,所以这块来周深。

请问一下,我重启下,保证这个效果啊,好来再重新刷新一下,刷请到了吗。

听到了吧,但是你想想这个请求什么请求是合洛斯不认吧,这是我们刚才说服务输出的东西吗,不是吧,因为什么它跳转到我们刚刚那个my control里面去了吧。

这时候把它改一下,我干掉,这儿返回一个信息,然后一个hello,这出来再重启,其实不用重启啊,不用重启也可以啊,重启一下吧,来再刷新一下,啥都找到了。

哪儿写错了。

刚刚合作写错了吗,这儿写错了啊,找一下,well pass,hello world back,干活哦,再加一个东西,没开微信,这不要加杠,这不要加杠,不要加杠,这不要加杠,这不要加杠。

啊申请一下嗯。

不知道问题吗,ctrl a ctrl没写错啊,来ctrl不是hello,我要去河道页面搞点htm,没错啊,周几。

诶这怎么还不对啊,我写的很多方法是不不是把没写错吧。

看这款my conversion写是吧,这是cl标记,标记等于hello,访问写的是msb。

没写错啊,虽然sb,然后四个赛。

request mapping,啊这儿是吧。

这是试玩还是粉丝。

这还跳回来啊,诶这啥情,是个目录,没墨了,这就放他那里面,没问题啊,确实一边。

request的map加,这不用加杠,这个问题吗,没啥事啊,这有什么屏啊,hello啊,这请求一个,加不加这加杠不加无所谓啊,这这这不是杠的事,没name等于他请求是他是一个和,应该写一个hell。

去掉不去掉,去掉之后不跟我意思不一样吗。

对啊,这哪有问题了,我错了,我刚才重新重新看一下,confusion是我们自己的,添加一个杠m m sb,然后呢发挥一个叫hello的一个请求,这样请求过来之后找到我们对应的一个梗。

这没写错啊。

之前测过了,这这应该不会有问题啊。

这波有问题,麦可麦,继承错了试一下,刚进行错了吗,来试一下啊,不是集成问题啊,这应该就应该写hello啊,这这起匹配的就是我们的河洛这个请求啊,有问题吗。

好的刘导吧,你这个说几下试试。

这个腰是set up flow game。

就过了,恐怖的是这两个问题啊。

要站起来,这奇怪了,rise刚出来。

rise control,没关系,这就是ctrl return一个hello,这是40,没导播幻引擎,魔幻级没关系啊,我现在没用到魔幻引擎,换诺手啊,诺手要试一下,弄出来试一下,是出问题了,奇怪了。

没看出来行。

这不对啊,不集成做累了吗,没写错吧。

在外边没c confusion。

这也不对啊,web,这不疼,不是他不是他,没写错,就是web,然后我会写这个,就这东西啊,这时间没问题啊,这个应该不应该出错啊。

这好奇怪啊。

是因为我加过滤器的原因吗,你想给自己试试啊,这我写的应该没问题啊,这是我们的数字连线,是msd,我是一你看啊看这意思啊,再看一下这个地方,现在我就加一个视图控制器,好,叫m sb。

然后设置它一个视图名称叫hello对吧,所以我现在相当于什么呢,我要请求一下我们的m s b,当我请求m s b的时候,相当于我映射到是我们的hello,这个这个页面里面是不是把它给请请请求到就行了。

是这样的意思啊,那我这写的时候,这个妈团中要这样写的时候,就应该写他写hello啊,这啥意思啊,就很奇葩啊。

又不让我请求了,需要用这两个名字换个名字也一样啊,你换一个a b c d就可以了,跟名字无关啊,爱着他,这应该没问题啊,这为什么会出问题吗,hello,肯定没问题,这不就写了个这这就写了一个天猫页面。

啥啥啥都没写,什么都没写啊。

这样我们先访问下楼,看能不能合作,能请求到,我这hello。

请求不到啊,这是controler,as you guys map return hello,我知道啥意思,好像好像这个问题啊,我们倒一个东西啊,额外加一个东西加一个。

找一下东西,找一个我们的依赖,找一个依赖,找一下我们simply和依赖啊,这很奇怪啊,福马克,我靠官网都不用了,什么离谱,吓死我了,来把这个一代加进来加一下试试,四。

这娱乐有关系吗,这次抱我抱我很意外啊,所以为什么找不到啊。

这就有了,我现在请求a b c d现在好了吗,好了吧,我说咋回事啊。

我们代码写的肯定没问题啊,待会来看,我来看刚好加什么,是不是a b c d,相当于说我请求这a b c d的时候给它加了一个视图,名称叫hello啊,叫hello,ok,这集刚出的模板引擎。

我刚刚那个目录放的时候是放这个呃,他们里面去了,这时候必须要加工引擎之后才能才能去便利我们这个他们的目录,要不然的话他找不到对应,找到对应一个属性啊,找找找到对应这个页面好,那这个时候不是就没问题了。

现在我放在a b c d改回来,m sb额外。

来再重新请求一下,这个还不行。

这个这个sb中毒了吗,重启一下试试。

好了现在说好了,是不是请求到了,因为我们没加了模拟引擎这块给大家标标注一下,注意需要添加,老板引擎,好吧,我刚刚给他粘出来的东西,给他粘过来,搁这,好了是这块东西好吧,稍微注意一下就行了。

知道你们自己试试,添加这个输入,输入节气就行了,明白意思吧,啊这块翻车了,浪浪费了点时间,不好意思啊,反正我刚写就感觉代码这块肯定是没问题的。

好吧,请过来就找不到折叠器,刚刚应该听折器啊,听折叠器早早就解掉了行了,这块咱们大家就聊这么多吧,啊别的不说了,来这边听吧,同学扣个一,知道哪有问题了吧。

系列 3:P67:【Spring】springMVC_概念引入 - 马士兵_马小雨 - BV1zh411H79h

好从这一节开始呢,我们就进入到这个s s m里面,第三个框架,这个spring mc mvc这个框架的一个啊,这个血线单说一下什么是我们这个spring mvc这个框架哈。

我们这个spring framework这个体系里面呢,那么就是我们那个i o c和d n那一块,这个a p a spect就是我们的切面编程呃。

gdbc这块呢我们加上了一个呃这个gd vc template,完成自身改查,同时呢又完成了一个事务控制,然后我们在这讲一个叫做spring mvc的一个这个框架。

那么spring mvc这个框架主要解决的是什么问题,他能给我们做什么。

接下来简单给大家描述一下,那么呃我们在这个呃我们说一下sumsor怎么来的,它是spring呃,framework的一个后续产品,它已经融合在了这个supreme web flow里面了。

那么也就是说我们要是想使用这个spring mvc的话呢,我们还是要借助呃这个spring 5的一个环境,或者spring的一个环境才能够使用它,它还是要依赖spring的。

那么这个spring mvc它主要是对哪一层进行封装呢,我们先说一下这个m v c是什么,m v c m还有这个v啊,还有这个c,这是我们这个软件架构的这个mv c模式,它分别指向我们这个三层。

那这个m指的是什么,指的就是我们这个model,那m o m o d model啊,是我们的模型层,还有我们这个d啊啊,针对于数据操作的一个模型啊,叫做模型层,模型层,那么在这一层呢我们讲了一个框架啊。

就针对于dao的一个封装啊,那么指的是哪个啊,这个框架呢就是我们这个my b,也就是说我们这个my bet c已经解决了模型层的一个这个增删改查,一个封装了啊。

或者是我们那个g d b c template也是针对于模型层的,那这个v指的是什么,which指的是一个view,vn e w view,view这块指的是什么,叫做视图层,嗯是吐槽。

那么视图层这一块的主要讲的都是一些页面技术,像一些这个html啦啊这个cs啦g啦,或者是我们说这个gsp了,嗯,在这个分层上,它也是属于这个呃模型层,视图层的,它主要是用来展现数据的。

那么这一层呢我们还没有接触过一些呃正式的一些框架,或者是前端的一些框架,这这层就算是有框架,它也是前端工程师的一些框架,可能对我们来说呢,这个框架相对来说比较模糊,那么还有第三层呢就是什么呢。

就是我们这个control层啊,这个control层,那么control层指的是什么,就是我们的一个控制层,控制层,啊控制词,那么这一层啊主要是通过我们之前是用什么技术来实现的呢。

用的是这个so well let技术嗯,缩短技术,那么这一层主要就是用来控制前后端数据交互以及那页面跳转,以及我交互的一个逻辑等等,都要通过这个控制层面进行处理的。

那么我们今天所讲这个super mvc其实就是对什么呢,其实就是对soviet的一个封装啊,就是我们今天的一个呃soviet封装,原始的时候我们可能会用这个呃so light,但是solar封装之后呢。

我们今天使用这个spring mvc这个框架来进行一个处理就可以了,那么你可能会说这才两个框架呀,那spring在这里面有什么作用呢,那就是我们所说的一个s s m啊,当然这个框架整合呢。

我们把这个m c m v c学完之后,我们在后续呢再去处理就可以了。

那么呃supremvc啊是什么,是spring v展现提供呃,呃展现提供的呃,我是为展现曾提供的一个基于mvc设计模式的,一个优秀的一个web框架之一,也是目前主要的mvc框架。

那么在他之前用的是这个struts和struts to,但是struts to呢在我们这个web 30之后呢,基本上就是属于一个淘汰的状态了,都属于这个spring mvc了。

那么呃spring mvc呢给我们提供了一套这个注解,你注解可以让普通的java类成为controller,而无需继承soviet,就是我们之前写control层,要写sol的话。

那可能要继承这个http soviet,那么我们以后再定义ctrl层的时候,就无需自己继承这个soviet了啊,那么这样的话呢可以实现我们的代码呢与soviet之间的一个jo。

就是后面我们在编写soviet的时候,其实我们不需要tomcat的一个环境,不需要so let api和这个jsp app,这h2 的话也是可以进行一个运行的,之后呢。

supreme m v c还提供了支持rest风格的一个url的一个写法,它可以让我们这个ul呢这个安全性可以提高一些啊,这样可以减少我们参数的一些暴露呃,supervisa还采用了一个松耦合哎。

可这个查询的这个主题结构比其他框架的更加的呃,具有扩展性和这个呃灵活性,那么这个是我们supremc的一个呃这个呃这个简单的一个介绍哈。

那可能大家对于这个surprimvc还是没有一定的一个呃这个呃感受,那么接下来呢我们就搭建一个呃这个web项目,然后呢我们从普通web项目到什么到使用spring mvc框架。

那么这样的一个转变转变之后呢,带大家体会一下这个spring mvc框架它的运行呃。

系列 3:P68:【Spring】SpringMVC_创建并运行war项目 - 马士兵_马小雨 - BV1zh411H79h

好,接下来呢我们就搭建一个呃外部项目。因为我们这个spriMAC呢主要是对于控制层来进行一个封装的。那么我们接下来就答应通过美文搭建一个外部项目来给大家展示的,也不是我们储通的一个炸项目。

而是一个腕项目了。呃,这块呢这个改了一下字啊,这不是一个查询,这是可热差的一个组件结构啊。那么接下来呢我们就搭建一个项目。搭建完项目之后呢,我们呃测试一下在man状态下的搭建项目这一块。呃。

然后呢再把这个MV框架给大家加上之后,看一看它有哪些变化哈。那首先呢我们创建一个项目,create new project。那么我们还是创建一个空项目。然后在空项目里面呢,我们可能会创建若干几个模块。

这样就省得我来回切换项目,每天一个就可以了。选择这个empty project,然后来一个next起个名字。名字叫做spring mVC啊,这个小写名MVC,然后来个下划线哦啊。

那么我们把所有的MVC的这个测试项目全放这就可以了。那么再来一个finishfinish之后呢,这个可以关掉哈,我们这个项目就已经创建好了。但是这块呢并没有显示我们的项目名。如果不显示的话。

你可以直接在这哈,可以在这右击直接new这个呃在这儿这个file直接new model model就可以了。那如果说你想显示这个项目名的话呢。

呃那么也可以在这块给它来一个叫做呃close project关掉之后呢,再点开这个sup mAC。然后你会发现这时候项目名就出来了。它就是我们的一个项目的一个根文件夹。😊。

那,创建完这个文件夹之后呢,下一步呢我们就要在这个项目中创建我们一个外呃这个外部项目,就是一个W项目。那么呃在创建W项目的时候呢,有一些细节的注意点,大家需要调试一下。在创建va项目之前。

我们需要干这样几个事儿。

呃,空项目准备好之后呢,我们下一件事就是我们要把当前项目这个maven和lo bookroom book可能给它设置一下。

因为这个maven和lo book可呢是针对每个项目都要单独进行设置的那我们创建新项目之后呢,这个应该已经失效了。所以这个小细节呢大家自己注意一下就可以了。这个还是非常简单的哈。

file,然后选择这个stting呃,找这个me文,这个me文呢指定成我们自己那个meve文。因为这块之前已经讲过了,那我这块呢就快速操作一下就可以了。选择它。

然后这块over ride选择我们自己那个ma文里面那个配置文件。呃,维稳。好,里面这个sing4点叉MO啊,把这个给它设置一下apply应用完毕之后呢。

我们顺便找一下这个compercomp里面有个叫做annotation processes,把这个给它勾上。那你勾上之后呢,代表你当前项目这个就支持 book的一个注解了。

然后最后来一个来一个OK呢也就可以了。啊,那么这个两个就一块设置了。设置完之后呢,后面我们创建项目就不用担心说这个me和这个room book插件一个问题了。

之后呢,我们就要创建一个maven的一个web项目的一个模块了。其实呢我们一开始直接创建这个模块也可以。但是呢我为了方便在ID中切换,呃。

不用再来ID中来回切换呢我们直接呢创建一个mave web的一个模块。

那么这个怎么创建呢?还是在这儿右击新建一个model,然后在model里面的时候,我们要选择这个me。

在选作me的时候呢,大家一定要注意哈,我们在创建ma呃呃va项目的时候呢,我们就要从这个create from arc type,从这个骨节这个archrctype其实你可以理理解为项目的模板。

也有这样一个称呼叫做股价。就是这个骨头的骨,然后呢架子的架。其实说白了就是一个项目模板啊,有人称之为股架,有人称之为项目模板。那么我们在选择这个骨架的时候呢,这个之前呢也这个提示过大家哈,呃。

我们要选什么?要选这个外bAPP这样一个项目。但是大家注意这块有两个外APP一个是这个外APP一个是这个APP但是大家注意哈。

前面这个外APP呢是叫做COO的一个APP而我们这块是一个的一个外APP我们要选择它千万不要选择上面这个选择上面这个就错了。啊,不要用它选择这个叫做moctype webAPP就可以了。

然后再来一个next我们起给这个模块呃准备一个group IDDcom点MSB。嗯,MSB哎,然后呢起一个名字叫做spring。MVC然后呢MVC的1个01个的一个项目啊,那我们在这块启占一个模块名哈。

这个没什么可说的,然后再来一个next呃,这个里面暂时也没什么可说的。这里面你看我们之前已经选择了me文,它就已经使用我们我我自己配置那个me文来来进行啊对我们这个项目的一个管理了。😊,再来一个nex。

就是我们当唉这个可以给大家截个图哈。这个是如果说你的这个在创建外部项目的时候,如果这里面不是你自己配置那个ma文的话呢,当然你使用idea默认的也可以哈,这个没有没有什么明确的一个强制要求。

其实都是可以的。

这是在这块来一个。下一步哈。

呃,这是查看这个目前你当天使用这个me,它会给再给你展示一下,然后再来一个nex,然后再来一个finish也就可以了。

那么这个时候呢呃你的idD呢会自动的先运行一一些东西。呃,这里边呢会默认往这里面怼一堆东西。怼完一堆东西之后呢,你可以先点一下这个叫做也呃可以在这块先点一下这个import这个 changes。

因为目前你会发现这里边给我们准备了一个外APP。但是明显看着它不是一个外APP那个结构。你先点一下这个import changes。点完这个inpost沉解词之后呢。

你会发现这个weAPP里面就带了一个小蓝点,那说明它是我们这个项目的一个资源的一个跟录径了,是吧?那那同样的在这个股价项目里面呢,项目股架里面呢,它给我们带上了很多东西。

像例如这块有一个呃nameURL,还有这个proty,它默认使用这个编辑工具是1。7的呃,结果里头用4。11的,还默认导入了一些这个插件一些依赖。那这些东西其实我们都不需要了。

我们从这个packaging以下后面的所有东西,一直到我们这个project的这些东西都给它删掉就可以了。哎,删掉完之后呢,我们重新的再来inport这个 changess就OK了。

呃不用它导入那些东西也是OK了。我们自己后面需要什么,我们自己导什么啊。

导进来之后呢,我们发现在一个呃使用股架创建我们这个spring的一个MVC嗯,这个ma的一个外部项目的时候呢,它有些毛病。这里边只有一个ma啊,它但是没有什么呢?没有那个就是像我们之前那种项目结构啊。

就这种ma下面有java有 resourcessources。然后呢除了除了min以外SRC呃,下面还有一个test的一个包。所以呢我们要把这些目录呢,手动的给它补齐,那怎么补呢?

呃,我们在SRC下面先补充一个什么,先补充一个directy叫做test,这是一个test目录。然后在ma目录里面呢,还有什么?还得有一个哎java目录。这个java目录是放java源代码的。

还得有一个什么呢?在ma下面还得有一个叫做呃RESOURCSresources目录。这个resources目录是放那个我们的配置文件的。然后在ts下面,我们再准备一个java目录。

这个java目录呢是放我们测试代码的。但是你会发现我们创建了这几个目录之后呢,它只是普通的目录而已,再点一下这个你跑的证据。这种普通目录呢并没有被我们当前项目识别为特殊的资源目录啊,那么怎么办呢?

我们需要告诉当前项目,这是特殊的资源目录,对这个文项目这个目录呢进行一个标记,那怎么标记呢?选中它右击有个叫做markdirecty as什么什么东西。那这个地方明显是放java源代码的那放什么?

放这个叫做source rootot,哎,标记为我们的这个叫做呃这个这个源代码的一个跟跟目录。那么这个resources呢是放配置文件的,它怎么做呢?

有个叫做mark什么mark叫做resources rootot那就是放我们这个资源配置文件的一个跟录键。在test下面这块有个java。

选择它右击啊叫做mark什么mark这个叫做test source,就是我们测试的这个原代码的一个呃这个跟录件啊,那么这样的话呢就把这几个配置文件呢给准备好了。准备好之后呢。我们再来看一下哈。

那么这个we部项目呢给我们创建的一个骨架,这个通过这个骨架给我们创建一个外部项目,我们发现在这个webAPP里面,它这个域它这个版本太低了。😊,就是我们之前在学习java意的时候呢。

我们用的这个呃web的这个约束呢,webAPP这个约束呢已经是4。0版本的一个约束了。所以这个约束不能用。那这个约束不能用呢?我怎么知道这个呃这个java意4。0这个we点叉里面这个约束长什么样子呢?

你可以在这块再创建一个什么创建一个普通的一个项目,普通的一个模块就是我们的一个java意的一个模块entterprise模块。

把这个web applicationplication的勾上勾上之后再来一个next这个名字你可以随便起一个AA是吧?finishfinish之后呢,呃它会给我们。

创建这样一个呃这样一个web项目,然后这里面不就有一个web点叉ML吗?我们把这个来给它cttrol C复制一下,复制完之后呢,给它粘这不就完了吗?这这之后呢,那我们这个AA项目怎么办呢?不要了。

移除这个模块,右击先什么呢?先这个叫做remove model,把这个模块移掉,移掉之后呢,这个文件夹也不要了,右机再来给它哎删掉就可以了。

那么我们当前这个webNF下面的一个web点叉ML它的一个版本,我们也已经指定好了。哎,那这就是一个呃整个web项目的一个创建,以及什么呢?以及我们这个目录一个准备就准备好了。

呃,准备好之后呢,那么我们接下来做一个简单的一个呃简单的一个呃这个测试。测试什么呢?就是这个项目怎么运行啊,对吧?哎,怎么运行,然后呢怎么编写这个controller,那么我们这个该怎么办哈?

我们先准备一个普通的serv light,然后呢请求slight调转GSP。那么我们先做一个这样的一个代码。这个这个代码做完之后呢,那么我们呃这个再把它改成这个sMV的哈。😊,这一步改完了。

嗯,我们先准备一个so light,然后呢跳转至GSGSP。在java这块呢,我们先准备一个controller层com点MSB点啊这个CUNTROcontroller。没有。

controller嗯来个点什么叫做呃my server吧。哎,让它去继承HTTPsolet。但是你会发现在继承的时候呢,这里面并没有找到这个HTTP soul light,这是为什么呢?

这个HTDP嗯。s light这个类呢它是来自于哪类呢?它是来自于呃这样的一个账包,这个账包叫做s light杠API。A片。那么这个s like APII在哪里呢?

它其实就是在我们这个tom cat里面。正式来说,这里面应该是不会有这个tom cat。我们可以先把这个删掉哈。所以这个一会儿啊他给我默认关联它了,我们可以先把这个给它删掉。呃。

我们用maven来这个呃这个管理我们项目之后呢,这个炸包啊导入呢全部都交给mave了啊。那么此时呢当前我们呃这个项目里面是没有这个slight APII这个炸的slet APII这个炸在哪呢?

在我们这个tom cat里面呢,可以可以给大家找一下哈。呃,地盘在这个program forAT,然后tom cat tom cat99。0。41。这里面有个lab。

然后lab里面有一个叫做slet APII。那么这个 APII还有我们这个在编写GSP的时候呢,还有个叫做GSP APII这两个依赖呢,在我们普通java意义项目里面,如果我们一关联t之间呢。

就会把这个两个依赖呀给导入进我们的项目,导入进我们的项目之后呢,我们编码就可以使用这里面代码了。但是运行的时候呢,我们还要把我们的项目放到我们这个t里面。所以事实上呢。

这两个依赖并不需要真正的导入到我们项目之中。但是编码的时候,我们还需要这两个。也就说这两种这两个呢它的这个这个使用级别呢仅是在编译的时候,或者是编码的时候需要。呃,那么怎么办呢?当前又是一个me文项。

me文项目需要导入这个swat APII和GSP APII那怎么办呢?我们只能通过这个me文坐标来导入这两个哎炸包了,那怎么导呢?我们可以打开我们这个搜索me坐标的一个那个那个那个网址MVN啊。

这个reposory点com。

在这里面我们可以搜一下,第一个叫做slight APII。搜索一下搜索完之后呢,我们看一看这是java X包里面的一个s APII选择它,然后里面有一个看看这个版本已经到4。0版本了。

那我们就选择这个4。0。1啊,你看使用最高了,已经是2728了,就用它就可以了。

呃,选它来ctrol C哎,放到什么呀?放到我们这个pome点叉M之中,在这放一个dependencies。

放进来。除了这个solight APII以外呢,还有一个叫做GSP APIIGSP杠API这样的一个依赖。那这个依赖呢我们也得导进来哈,这个是它。

呃,用的也是新一点版本吧,2。3。3就用它了。来ctrl C拿过来也放到这个里面。

嗯。这个是一个加格注释,这是sve light和这个GSP的这个依赖。你来。导进来之后,点一下这个import changes啊,注意哈,在导入这个slight APII和GSP pad的时候。

你会发现这里面有个scope,这个scope都是一个叫做provid的意思是什么呢?就是编译的时候也不编译它。仅仅是在我们编码的时候,编写的过程中呢,使用这两个依赖。那么事实运行的时候呢。

我们把这个代码放到一个容器中,容器中自动就给我们提供这两个依赖了。所以呢这个是呃scope provided它的一个作用啊。那么导入进来两个依赖之后呢。

我们这个my server里面就可以让它去继承ext HTTP。HTTP哎是外了。喂。S。SERV啊,我应该是还没有成功导入。呃,我们先把这个这个me的一个导入给它重新处理一下哈,在这里。

右击ma问呃reimport一下。po一下,我们点开看一看,这里面已经应该有这个slet APII和GSP APII了。那么我们再到我们自己的这个代码里面找一下哈。Ex H, T, T P。

server light。exts hTTPserv light,但是好像没有提示,没有提示,那就手动放进来吧。鼠标放进来,然后点inport class a就导进来了。

那那这是一个导进来了一个HTTPserv light。然后呢我们还来还是要干嘛呢?还是要重写这个service方法嘛啊,来一个service方法。呃,那么我们这块做一个页面跳转。

我们要给它跳转到我们在这个外APP里面呢,我们准备一个叫做。呃,FIRST first1个GSP吧,然后在这写成一个叫做this is first。点GSP我们要往这个页面上去跳,那怎么跳呢?

它直接放到我们这个外APP下面了,就是放到我们这个跟外NNF同一个级别下面了。那我们就请求转发请详象同像其实都行。

请求转发吧QQ点get request然呢请求转发至我们这个FIRST first点GSP上去,然后呢并做出转发动作报IQP。那么同样的我们要给这个呃my soul呢准备一个什么准备一个请求映射路径啊。

再来一个什么再来一个艾一个叫做web soullet请求映射路径呢,我们直接写成什么?直接写成一个做呃斜线my server civil点 do哎就可以了。那好。

那么接下来呢我们启动一下我们这个项目来看一看这个呃这个项目该如何去去去这个呃请求我们这个m light哈,该如何去启动。那么我们创建个vi webb项目之后呢,你这里面可能还没有一个启动的服务器。

那怎么办呢?我们可以手动添加一个,例如我们在这添加一个什么,添加一个呃这个tomca一个serv。然后呢,一个是logo,一个是本地,一个是远程。那我们添加本地这个logo就可以了。

再加本地运行环境的时候呢,第一个这块要起个名字。那这个名字呢我们直接写成tom cat9就可以了。然后前面这个首字母大不大写无所谓啊,就当便代表你当前这个服务器的名字。

那服务器这个application server在哪里呢?因为我这里面已经我ide已经这个整合过这个9。04了。如果没整合过的话,你这块应该是空的空的那怎么办呢?你点一下这个confi去找什么。

去找你的你这块有可能是一个空的空的干嘛呢?你就按照这个路去去找找你个这个这个的这个路径啊,选择到这个上一层然后O然后下面这块呢自动就跟着变了这个GS自然而然就进来了。

那么你这块点这个confi配置完之后呢,这里面就会有一个9。4了。但是我这块已经配置过了,我就不需要再重新配置了。那么配到这之后呢,我们下面的东西先别动啊,先回到这个deployment这一块。

我们先把什么呀,先把我们当前这个supreme mVC01这个项目呢给它部署进我们当前这个服务。呃,这个这个容器里面那怎么部署呢?点这个加号artact选什么?选我们这个叫做哦。

我之前这里面创建1个AAY exploitloed的,已经删掉了,它还提示我呢,选谁呢?选这个supMVC01Y exploited,把它部署进来。部署间之后。

这个application contactt就是上下文路径,或者是你简单理解就是我们访问的时候,项目这个名字,你想改的可以改,你不想改的话呢,你这样也行这样也行。然后再回到这个server这块来。

你会发现呃,在我们项目启动之后,默认用什么浏览器打开呢?我默认用这个火狐吧,可能我更喜欢火狐一点,是吧?on update actions那给它改成什么呀?

class 呃up classes and resourcestheon frame declaration这块可以改成up resources。

或者你改成下面这个up classes and resources也可以啊都行。有。那么下面这个是1个GRE默认的是什么呢?默认就是我们当前项目这个呃1。8161就OK了。嗯。

当然deeffat也是行的哎。呃,这块可以使用这个呃这个这个deeffault,我们就给它改成GDK1。8吧哎。这个GDK181611。8。0161,这是我自己安装的那个GDK是吧。

或者是用这个GRE啊也都可以用它了。这个是我们呃服务启动的一个端口号8080啊,那你想改的话呢,可以给它改一改。例如88998081是吧?下面是GMX1个po,这个就不用动,1099就完事儿了。哎。

然后再来一个apply ok。那你会发现这个时候上面就多了一个tomca9,我们就可以用这个tom cat9来启动啊,启动tomca9之后,把我们这个项目呢自动的给它部署到我们这个tomca9里面。

但是大家一定要注意哈,此时我们的项目这里面还有没有编译呢?并没有编译,它并没有编译成一个可部署的项目。但是我们一启动这个tom k9的时候呢,它就会先对这个项目进行一个编译。

然后自动的给它部署到我们这个tm k9里边。那真的是这样吗?我们可以试一下哈。点下他。这里面应该会有一些这个日志。这个第一次启动打印日志还是挺挺挺这个挺耗时的哈。

好,那么成功打开了我们这个呃tom cat9呢已经成功运行了。成功运行之后呢,你会发现我们这里面也多了一个target目录,它就已经对S2RC里面东西呢进行一个编译了。编译完之后呢生成这个样子。

classsses是看代码的,然后这个super m呢是看我们整个项目打包之后的一个结构的forGSP在这儿啊这个indexGSP在这外NF里面有classclass呢在在这里面有一个我们的一个controller。

在这块也有。那我们试一下访问这个my server letter do啊,看看它能不能给我们跳转到这个first这个点这这个first点GSP上去哈。那在这怎么访问呢?

直接在这儿访问这个叫做呃my呃 my server light点 do,然后一回车,你会发现成功的给你跳转到了this is first gSP调转到这个位置上去了。那么整个的一个用创建外部项目。

并启动外部项目这块呢给大家演示了一下了,演示完之后呢,那么下一步我们就是在这个上面呢使用s mV框架,对我们这个con层对我们这个serv light进行一个替换啊,替换为s mV就已就O了。

系列 3:P69:【Spring】SpringMVC_框架搭建1 - 马士兵_马小雨 - BV1zh411H79h

我们创建了一个可以正常启动运行的一个maven web项目之后,那么接下来呢我们就要在maven web项目里面呃,这个导入我们这个mvc spring mvc的一个框架。

然后有了super mvc框架之后呢,我们ctrl层就不用这么写了啊,就我们自不会再再也不会自己去这个写这种啊,so let或者继承这种sol了,呃那么我们自己写这个select呢有很多毛病。

第一个毛病就是呃我们这一个soviet它都有一个独立的一个应试路径,那么如果说我们针对于一个啊,这个我们假设想在一个server之中定义大量不同的这些业务逻辑处理的话。

可能会产生很多很多的这种搜罗来的对象,因为你这个每个搜来的只能对应一个应试路径嘛,对不对,那么我们想在一个类里面啊,可以处理很多很多不同的这个路径或者不同的请求的话,那么我们嗯怎么做呢。

就得用这个spring mvc框架来给我们处理的,这是第一个,第二个呢呃我们在获取页面参数的时候呢,可能要通过这个request对象去获取,获取完之后呢。

我们还要把这个request对象所获取参数的封装成什么,封装成对象,然后再把对象传给我们的这个思维一层,再把对象传给我们这个这个d o层,然后一层一层逐层的呢呃去这个进行一个处理。

那么我们有了mvc之后,supremvc之后呢,我们获取参数这一块呢也再也不用自己去手动去获取request,get premeter map了,get permeter了。

那么完全有这个40框架自动给我们获取参数就已经ok了,包括后面的请求转发和想要成像啊,都有一些简化的一些写法啊,那么简单来说spring mvc是干嘛的。

其实就是把我们这个呃control层对于我们的so light进行一个封装的一层框架,那么接下来既然用四fmc来替代我们这个ctrl层了,那么我们接下来就不写这个my sou了。

直接把这个my soul light给他干嘛给它删掉。

删掉上弹完之后呢,那么接下来呢我们就要引入我们这个super mvc的一个框架。

但在引入super vc框架这块这块就要添加依赖。

那么都要添加哪些依赖呢,这个依赖呢我都给大家准备好了。

大家可以按照这个呃,我把我这个依赖拿过来之后呢,带着大家阅读一下啊。

这个依赖已经带了dependency了,我们把这个从上往下给它复制一下。

来,ctrl c复制一下呃,复制完之后呢,往这一站,那么第一步导入这些依赖来import changes一下,你自己慢慢打就可以了,这应该很快就倒完哈,人你会发现导入了这么多依赖哦,我的天呐。

怎么这么多是吧,给大家解释一下,其实如果说我们要是想单纯的使用这个spring mvc框架的话,是不需要导入这么多的,那需要导入哪些呢,需要第一个spring gn context。

这个context里面还要依赖谁呢,还要依赖我们这些,这个还要依赖我们这个呃这个contact里面像a o p r b和core expressions啊,这些还是要依赖的。

因为我们这个preme mission它是作为一个spring的一个延伸,它还是要在spring这个核心框架基础之上再继续进行一个使用的,那么切换编程这一块呢,其实不导弹也行,我不知道他也行。

因为这个呢是我们后面这个a op的一个内容,但是将来呢我们要面临的一个问题是ssm整合到一起,这些炸包将来早早往往也要需要需要用到,那么暂时呢这个放置也是ok的。

这其实就是我们之前做的那些东西的俗的依赖,然后op联盟啊,德鲁伊连接池连接数据库的这个connector,j d b c包,tx 85包,om自动运输包,还有com login,com login。

其实找不到也无所谓,因为目前spring日式这一块呢,我们使用的这个呃这个logo for you to,那我这块用的也是一个logo for you to,那我们看一下这块。

我用的就是一个呃呃这是一个log for j2 的一个日志包,如果不插件,这个自然啊放了是吧,还有我们的spring测试包,这个我们直接用这个5。3。5这个版本了嗯。

还有这个我们用的这个g unit也是用直接用这个五这个版本了啊,那么我们这个直接用最新的,还有我们这个spring告web,spring杠web,这个是我们新导进来的啊,这个是spring的。

在web这块支持一个沙包,这块还有个spring mvc包,就这两个包,这两个包是我们新到进来的这两个依赖,那么要是想使用我们这个super mac的话。

这两个依赖是是我们今天呢在这个呃今天在这里新增的之后,这个呃so let api和jsp api在这块倒不倒就已经无所谓了。

为什么呢,因为这个东西它是放在我们这个服务器的环境区运行的啊,我们在这个编码中已经不需要直接写这个so let和jsp了,所以呢暂时是不需要打他也可以的,那么这个倒了也没关系。

因为我们的项目在打包的时候,因为这个scope控制是一个provided,他也不会打进我的项目,所以这块呢暂时放着吧,那方便我们测试自己写so let以及gsp上的一些东西对吧。

那么这个是整个呃这个导入依赖的一个简单的一个介绍,导入完依赖之后,下一步就是要开除我们这个呃spring mvc的一个这样的一个编码了哈,之后呢,接下来我们在呃开发这个项目后面要干什么事呢。

呃我们说这个之前给大家总结过哈,这个但凡是框架的使用都分为这样几部。

第一步倒依赖,第二步呢做配置文件,第三步干嘛呢,第三步这个呃这个就是我们的一个运行测试,那么呃接下来我们跟大家说一下,这个简单说一下这个spring mvc它的一个这个呃这个在在在配置super mc。

在使用的时候,我们需要做的几件事,呃第一件事呢这个引爆的真实怎么总提示我导入再导一下吧。

呃我们spring mvc框架在使用的时候呢,呃那么呃需要注配置一个东西叫做这个叫做一个核心的一个啊控制器。

呃,这个super m vc这块呢我们需要配置一个什么东西呢,我们需要配置第一个东西叫做前端控制器,那这个清单控制器它是一个什么玩意儿呢,可能现在大家这个东西有点抽象,不是很好理解,给大家说一下啊。

呃我们的这个sprmc呢,对于我们这个嗯对于我们这个呃ctrl层进行一个封装。

那封装之后呢,那个这个ctrl层呢还是要我们自己去写的哈。

就是我们的程序里面可能有多个control control 1 ctrl 2 ctrl 3,ctrl 4,还写成一个还是a c u n一啊,ctrl一这个叫做c u n c o n2 。

然后再来一个cn cn 3啊,还有一个是cn cn 4,就是我这就是我们程序中多个control嘛啊当然了,现在这个control呢已经不再是我们那个so let,是我们自己单独单独去定义就可以了。

嗯那么我们想请求某个control的时候,肯定要通过这个浏览器在地址栏上写一个这个路径才可以,例如我们的一个叫做叉叉叉叉叉的一个项目,然后后面写成一个叫做c o n e啊,或者是二啊,或者是三呢。

我们想请求哪个ctrl在后面写这个路径就可以了,但是一写这个路径之后啊,那我们这个ul凭什么能找到对应的control呢,这里面需要一个前端控制器啊,那个前端控制器,前端控制器,那么这个前端控制器呢。

呃你这个请求呢会先到达这个前端控制器,那你说这个东西怎么会先到达前端控制器呢,前端控制器需要我们自己配置一下,它可以拦截一下,就是您所请求的这个这个路径先走他,然后在前端控制器这块呢。

它要控制判断一下啊,你要反问哪个资源,访问哪个资源,往往哪个资源之后呢,那么他后面其实还有一个环节叫做什么呢。

还有另外一个环节叫做嗯,这个叫做处理器映射器,叫做handler mapping,但是这个hello mapping呢暂时我们不需要控制啊,暂时我们不需要控制。

那么暂时呢这个先不讲解它,我们先说这个前端控制器,这个前端控制器呢根据你的路径啊,给你匹配到对应的control是哪一个,那是哪一个嗯,就是你这块写了一个一了,然后走他他给你看哦,你走了之一。

那好给你调用这个ctrl,然后去执行,执行完之后做出响应,做后续操作就可以了,所以呢我们要配置一下这个前端控制器,那么前端控制器在哪里呢。

这个前端控制器其实就是spring mvc里面给我们提供的一个so light,这个so light叫做this parture,你this parture,so light。

这个so由这个so light呢来给大家呃,这个这个ctrl做一个这个分发的一个处理啊。

那这个怎么配置呢,呃我们知道这个so let呢是在我们这个web点叉ml中配置的。

所以呢我们要在web inf这里面去进行配置就好了,那么首先我们说一下这个so light的一个基本配置,一个是so light,然后呢之后还得有一个so let mapping,那solar的卖品哈。

select name这一块呢我们先空着吧,我们先把这个对应的so eclass写上,它是一个叫做d i s p a t c h r dispatcher soviet。

一回车你看它是o n g spring framework web包里面的一个soviet,里面的一个dispatcher soviet,那么这个soviet呢它的一个soviet name。

我们自己随便写一个吧,叫做departure so let就可以了,然后呢我们给这个departure soviet,给他一个请求的一个运输路径,那么它的运输路径是什么呢,这块呢我们就要好好斟酌一下了。

直接写成一个斜线就可以了,这个呢我们在讲java的时候呢,学习过就是你这块写成一个斜线,代表拦截所有的这个so light啊,拦截所有的路径,但是不包含g s p,那如果你写成一个斜线性的话呢。

就既包含了包含了所有的请求了,也包含了j s p了,所以这块呢我们暂时不包含g s p就可以了,因为g s p呢跟我们这个ctrl层其实本质上并没有什么特别明显的关系。

我们只拦截所有的这个出jsp以外的资源就可以了啊,那好那这个departure so that,配置完之后吧,还有另外一个小问题,另外一个什么小问题呢,就是我们后续的controler都要给它放到这里。

都要给它放到我们这个com。m sb。ctrl里面来,那既然都放到这里的话呢,这不ctrl层呢已经不再是需要继承sol的一个普通的一个账号的对象了,那我怎么知道这些呃这个control都在这儿呢。

我们需要在我们这个resources目录下面准备什么,准备一个核心配置文件,那这个核心配置文件,spring mvc的配置文件,那个spring mvc的配置文件怎么写呢。

在这写成一个叫做spring spring mvc mvc点叉m这个配置文件,我们要通过这个supremc点叉ml配置键来指明我的ctrl都大都在哪里,但是这个spring。m嗯,mvc。

x ml这个配置员怎么写呢,我们知道啊,这个supreme m v c它是拓展自这个spring的。

所以它的配置文件格式呢跟我们的supreme的格式其实是一样的。

我们把spring那个配置性的约束头拿回来就可以了哈,这个呢是我们之前做过的一个spring的一个约束。

那把这个约束头拿过来,来ctrl c复制一下,往这一放,放完之后呢,在这边写成一个斜线啊,b就ok了,那么这就是一个spring mvc的一个配置文件,在这个配置文件里面我们要干一个什么事呢。

要扫描control层,扫描啊,c有问题,of control什么意思呢,就是我们的control层它也是一些呃这个类和一些方法,那么也可能需要一些对象去调方法,那么在我们spring mvc那块呢。

我们spring那块呢我们已经学过了这个包括描这个东西,那同样的我们也需要啊,让我们这个这个mvc呢进行一个保存苗,那扫描哪个包呢,我们要扫描这个control层下面说的这个类,那怎么扫呢。

用这个叫做context component scan come,点m sb扫这个负极目录就可以了,在扫负极目录的时候,就自然而然把这个ctrl ctrl也给我们扫上了,那扫上之后。

那么接下来呢我们就要想了,那在这个web。x秒之中,我们这个dispatches of light,它要区分要找到我们这个control在哪块,那他怎么知道这个control在我们这个包里呢。

它需要读这个我们spring mvc这个配置文件,就是这里面要读谁要读我们这个spring mvc这个点差面这个配置文件,通过这个配置文件里面的配置信息能够找到ctrl层选在这。

那么也就是说现在有这样一个逻辑哈,就是从这个web的插标之中,我们要读这个配置文件,通过读了这个配置文件之后,哎,找到了所有的control选在这,全给我们实例化,是这样一个层次结构啊。

那怎么配置这个配置文件呢,用这个东西叫做in need pl,这个in the pol,我们在讲那个so light config对象的时候呢,已经提过这个事了,就是提供一些初始化参数。

它有一个叫做呃context configuration的这样的一个属性啊,就是它的一个项目配置一个属性,然后permit viper py这块可以写成一个class path字节码路径。

下面的一个spring mvc,点差秒就读这个配置文件了,然后在这块呢我们再加上一个叫做load on startup,项目,一启动就初始化,我们这个dispatch soviet叫做前端前端控制器。

那就可以了,那这块呢我们给大家加一点注释,这是一个配置前端控制器,前端控制器,然后呢这个前端控制器呢这块提供了一些初始化参数,这个初始化参数,初始化参数参数它是指定什么呢,是指定spring嗯。

mvc配置文件的这个入境的,或者是读取这个配置文件的,然后呢这个low down start up,这个是tom开的启动,记什么记忆初始化就要就要记,立即诶立即啊初始化这个sol light。

你放一个漏当star法唯一其实不推荐一,但是没事,协议也可以哈,那这一块呢就是一个so light map,就是我们当前这个前端控制器它的一个请求运输路径了,那么这个u r l这块大家需要注意一下。

它是匹配什么,匹配匹配所有的资源,所有的路,所有的路径除了什么,除了这个呃,这个g s p g s p。

那么我们的请求,任何请求只要不是js p的任何请求都要走这个前端控制器,而这个前端控制器呢它会根据我们自动分析我们请求的运输路径,然后呢去给我们调用ctrl层里面的一些代码就可以了。

那么这个是我们前端控制器的一个配置就搞定了。

这个配置搞定之后呢,呃那么呃这个包扫描呢也放了这个视图解析器。

我们后面再说哈,那接下来这个log fg 2点叉面,这个加不加都行。

因为这个呢我们spring mvc呢它也是supreme的一个这个延伸嘛,所以呢supreme呢这块要使用log for j2 来打印日志,那么我们也使用这个log four加二来打印就可以了。

当然这个你不加,其实目前暂时也没事儿。

log for j2 点cml往这一粘啊,粘上就可以了,那么如果说你想打日就打日志呗,呃你想打这个debug的可能太细了,那就可以调成什么,调成info i n f o这块调成info之后呢。

这块也可以调成i fo,就不用打印那么细的这个日志啊,当然这个后面如果说你想调的话,那再调也可以,当然这个暂时先这么地吧,因为目前好像还没有什么日式需要打印,所以它也不会显示什么东西啊。

前端控制器这一块的,我们配置好之后呢。

呃那么我们supreme的这个mv 4个核心配件也准备好了之后,这个写什么在哪呢,在这个呃r e e s o u r c resources啊,这个下,添加什么。

添加这个spring mvc点插边的一个这样的一个映射文件哈,那这个视图解析器呢我暂时没写,后面呢回头咱们再说他能干嘛啊,先不管它呃,之后呢就是定义我们的ctrl层处理器了。

呃那么我们在使用mvc这个框架下。

我们的control呢就不用再去继承我们什么,继承我们这个继承我们的这个呃叫什么叫做呃,叫做叫做这个htp so light了,我们写成普通的jv类就可以了,例如我们写成一个叫做my my cn啊。

看出来需不需要继承任何东西呢。

不需要继承任何东西呃,不需要继承任何东西了哈,诶那好开始呃,这个定义我们自己的control。

系列 3:P7:【多线程】锁的细节1:锁重入 - 马士兵_马小雨 - BV1zh411H79h

我们继续,下面我们来聊锁的细节,这个细节啊就超级超级多了,现在是九点半,要到哪儿算哪儿,我们首先来聊第一个细节,叫做锁重入,所升级。

那我们先来聊第一个细节啊,这个是。

所升级几点一。

好,锁重入,好了,同学们,我们先来聊什么叫锁重入,首先第一点呢,这个,synchronized写错了,呃syronize呢是可重入锁的,这新来的必须是可重入锁,那这个呃什么叫做所所所重入。

这个大家能理解吗,也就是说你看啊我有一个方法m这个方法呢是synchronized,他家的锁呢是o这个方法里面调了另外一个方法叫n,这个n呢哎他家的锁也叫o里边也是sonnet。

所以就相当于给这把锁上了两次,你发现没有,就是synchronized的m调n的过程,先给m上把锁,然后调到n的时候又给又同一把锁,我又加了一次,好像这里这个没问题吧,啊这一层一层的,我同学在那聊思索。

你在你在你在说啥嘞,这个不叫死锁,这个叫synchronized,是一个可重入锁,它必须得是可重入的,你知道为什么吗,比如说你的子类里面的实现这个m它是synchronized。

你的父类是synchronized,大家知道我们一般在这个子类的方法里面,我们完全可以调super。m没问题吧,如果你的这个siri不可重入,那就完蛋了,这种这种写法写不出来了啊,所以首先第一点呢。

synchronized是可重入锁,那可重入锁的概念就呃就就这个细节就来了,同学们,你们想想看这个可重入锁他在哪记录了,他重复了多少次呢,这事你们知道吗,有同学说老师记录在mark word里面锁一次。

我就加个一锁一次,我加个一,这样可以吗,这个可重入锁是必须得记录下来的啊,可重入次数,必须记录为啥嘞,重复次数必须记录,为啥嘞,因为,要解几次,解锁几次必须得对应,你重复两次就得解两次。

冲了三次就解三次,你要不记的话,你都不知道你解锁解几次,所以冲次数必须得记录,那记录在哪儿呢,好听我说这个不同的实现不同锁的时间是不一样的,我们先说偏向做实验,偏向索记录在县城站里,每增加一次。

每每重复一次,每重复一次,这时候怎么办呢,加一个log record,可以好说一下这个过程,这个过程是这样的,认真听,同时解释,刚才有同学问老师,那hash code去哪儿了,难道说你加了锁之后。

你还是扣的就访问不了了吗,不是不是解释这个过程啊。

那图调出来。

大家看这里,你来个对象之后啊,这里边记录了hash code,当然大家记住这个hash code,你没有调用的情况下,这里面细节也比较多,这里面的雕呢还是code,叫做identity还是code。

如果你不知道去百度identity还是扣的,注意它并不是我们自己重写的,还是code,它是identity code,ok那么如果有调用的话,这个hash code就记录在了我们的mc word里面。

那么这时候如果给他一上锁,你们看到了这里面就变成现成指针了,那现在第一个问题是,这还是cod跑哪去了,好我告诉你,所有的锁hash code都存档了,存到了自己的县城站里,听懂了吗。

存到了自己的l r这个record里面,这个record呢有一个指针指向一个数据结构,这个数据结构记录着前面这个状态的被做,用来做备份的mark word。

这个我们一般称之为叫displaced head,displaced head,可以替可以替代了已经可以替代的那个孩子,就是你认为他是个备份就行了啊,displaced mark word,那不好。

这个概念没问题吧,我们可以继续吧,所以如果是偏向锁的话,你要重复一次怎么办呢,就在这里再生成一个a l r,但这个l r里边这个值这个指针就是一个空值啊,因为不需要再记录了,我已经给记录下来了。

如果再重复一次,就再来一个,我要解锁的时候弹弹弹走鱼尾纹,弹完之后,我这锁就解了,好偏向锁是这样的,轻量级锁跟这个类似类似,依然是lock record,备份自己的原来的mark word。

接下来接下来就是你记录它的次数,每每每来一次生成一个l r l r弹完锁解开重量级锁的信息,我们没有仔细读,如果我没记错的话,这个你们去验证一下,它会记录在object monitor的一个字段上。

这个呢是惊动了操作系统的重量级锁,重量级所能处理的方式跟这个不一样,它会记录在object monitor一个字段上好了,关于可重入这件事,没问题了吧,不是replaced,是displaced的歌。

陈大哥啊,陈大吉,好所以锁重入这件事就是很简单。

不管你是偏向锁还是自旋锁,好那么接下来如果你是重量级锁,这我需要验证一下啊啊一个小小的问号,打一个小小的问号,应该是object,monitor的某一个字段啊,都是它的指向了一个对象的某一个字段手啊。

好了我们先不管了啊,先把这个略过啊,我说过啊,有些细节呢其实面试官也没有人问过啊,有时候我也懒得去找,找着东西呢,很无聊的,知道吧,面试官不问,我真的懒得着,我跟你说,并不是说读不会读,读不会读不懂。

我是懒得花这精力,人的精力总是有限的,刚才有同学问我了吗,说老师你是怎么平衡工作生活这些东西呢,没有平衡,只有取舍,人的经历也一样。

你同样的这个时间,你你你你你给了工作就不能给生活,给了生活就不能给工作啊,girlfriend a girlfriend b,你现在是2月14号03:05:48,你给他就不能给他,ok这个没有平衡啊。

我们重录这块就聊到这儿好,除了重录之外呢,我们呃再来聊一聊呢这个实现的一些小小的细节啊,就是所升级的过程之中的一些小小的细节,这个细节呢你认真听嗯。

嗯好。

大家听我说呃,这个细节呢是什么样的呢。

这个图没给他抓下来是吧,这个图也给大家抓下来。

好把这图给拿出来了啊,可不这图。

这图,嗯把这图给大家拽下来。

下次我要在讲类类似内容的时候是吧。

我觉得没有必要,每次都切来切去了啊。

复制图片到mx 64,这个叫,lock step by step吧。

就这个啊好,我们来看这个呃这个过程,这个过程呢有一些细节被我略过了,我们一点点来讲呃,我们首先讲这块的细节,这块细节是什么呢,就是我们刚才说偏向锁升级为轻量级锁,这时候只要有一个线程抢。

它就会升级成轻量级锁,只要有一个线程抢就升级成轻量级啊,当然这是偏向所启动的状态,如果偏向锁没启动,那么普通对象就直接升级成轻量级锁,那么现在问题呢我要讲给你讲清楚的是。

轻量级锁什么时候升级为重量级锁。

好看,这里,这叫自旋锁了自旋锁,什么时候升级为重量级锁。

为什么又变黑了。

why,我的问题啊,自旋锁啊,什么时候升级为重的一所呢。

大家听我说啊,这个过程呢我把它放到前面来啊,这个呢是竞争家具,什么叫竞争加剧呢,就是有线程超过十次自选,哈哈就有的人啊,你你不是一人一个人跟着大便,边上的人跟着自旋吗,在这等着吗,如果有的超过十次了。

或者是自旋的线程数超过cpu核数一半,你16个核自旋的线程已经超过八了好了,这个时候像是升级为重量级锁,听懂了吗,当然十次自选,你是可以通过参数来控制的,这个参数呢叫pay block stin。

你自己去控制啊,ok这叫做呃自选,当然这是1。6之前,1。6之前你如果聊jvm调优啊,老师不是讲的jvm调优课吗,如果1。6之前,你居然这个参数是可以调的,但是我告诉你1。6之后不要调了,为什么。

因为这时候1。6之后呢,加入了一个叫自适应自旋,叫addictive of spinning,到底多少次,以及它有多少个线程,这件事由jvm自己来根据算法来控制,所以这个不用你调了。

所以第一个问题就是细节上的问题啊,呃自旋锁什么时候升级成重量级,这点没问题吧。

有没有谁有疑问的,没问题,这个老师可以还能跟上吗,嗯对更智能了。

不需要你调了吗,还能跟上是吧,细节越变越多。

就大家跟着就就就慢慢越来越费劲了啊。

系列 3:P70:【Spring】SpringMVC_框架搭建2 - 马士兵_马小雨 - BV1zh411H79h

好接下来呢我们定义我们这个ctrl层的一个代码哈,呃那么在spring mvc下呢,我们就不需要自己去这个呃这个继承这个htp server light了,但是我们需要在这块加上这个东西。

叫做at control,呃,这个at cla这个注解呢我们在讲spring的时候,其实已经提过了,这个其实是哪个注解,是这个at component,component的它的一个子主写。

那么这个at computer呢有三个子路解,一个是i,一个是at的service,一个是at repulsory,一个是at controller,那么我们今天终于用到了这个control了。

但是这块就不用它了哈。

什么意思呢,意思就是我们加上这个数据之后呢,呃在我们spring这里面有扫描了一个com。m s b。

它一定会扫到这个类,走到这个类的时候,一看这块有control,那么就自然而然就会把它实例化,跟那个at control是一样的,但是因为这块是一个control层。

所以这块呢我们要选择用这个at ctrl这个主题,结果我们之前在实例化service的时候,这块加什么,加这个at service是一个道理的,但是这块得加at rol啊。

看出了哎好交叉的ctrl之后呢,呃那么下一步就是要定一个什么,定义一个处理方法,定义一个处理请求的这个方法,那这个方法怎么定义呢,这么定义的,随便写成一个吧,来一个public返回值。

为什么返回值为string,起个名字叫做什么叫做f i r s t first,什么first,看出来,那就是我们自己定义的第一个ctrl,然后我们return虽然随随便return个什么东西吧。

那我们说这个方法它这个定义这个格式,怎么这块非得是string呢,我们先解释一下哈,这个返回值返回值定义为string啊,ring嗯,spring其实是什么意思呢,其实就是呃用来用来用来返回什么。

用来返回,用来这个表明什么呢,表明啊这个呃这个界面啊跳要跳转的,要跳转的啊,这个呃这个这个页面页面的路径,也就是你一会儿请求到我们这个方法之后呢,那么我们这个处理完之后,中间可能经过了一系列处理。

处理之后呢,做个页面跳转,那页面跳转的话,你直接把要跳出那个页面路径都放这就可以了,他一直turn自动就给你跳呃,那么这个不同于什么呢,不同于我们之前那个呃service方法。

你service方法在service方法里面呢,它给我们封装了这个类似于这个http servlet request iq,http。

so that response a response r e s p啊,它类似于它给我们定义了这样的一些呃对象呃,这块呢再来一个什么,再来一个void void,诶诶。

那么在这里面呢我们自己在定义ctrl的时候呢,因为已经没有继承这个http so light。

也就没有重写这个思维方法,自然而然的呃,我们暂时就就不用这个request和response。

也可以做这个参数的接收和相应的一些处理了,那么处理方式就会有差别,这个是一个word没关系,那我们这块这个可以换成一个string就来指明什么,指明我们要跳转那个页面路径。

当然后面这块也可以换换成末端的wave也可以啊,你好呃,呃这个呃,那么这个可以给它先删掉。

知道之后你可能会说,那这个请这个控制层如何接触页面参数啊。

啊也可以接受,那是我们后面下一步动作了哈,那么我们接下来需要通过浏览器来请求什么,请求我们这个my control里面这个first control,那么我们可以在这嗯输出语句。

输出语叫做f i r s t fc u n t i o cl,那我们说出一句,看看能不能请求到他哈,请求到它之后呢,我们接下来要由它这个页面跳转到哪里呢,跳转到我们这个first js p呢,怎么跳呢。

这块直接写f i r s t first。jsp就可以了,那么直接写成我们要调整的一个文件的一个页面的路径的名字就ok了,ok之后,那接下来我们还面临一个问题,就是我们在乱七的地址栏上。

最后呢要写什么东西才能映射到我们这个这个处理器这个方法呀,对吧,那这个处理的映射路径是什么呀,我们之前用的这个注解呢叫做at web so light。

但是这个at web so light只能给这个类上定一个请求的一个映射,那我们要给这个方法上定一个请求,应试路径用什么呢,用这个叫做at request map,request就是请求的意思。

map就是映射的意思,就是你在请求的时候用什么路径能映射到这个方法呢,是吧,我们可以写成一个来一个冒号斜线,叫做first cn嗯嗯t cl,那看出来点度吧,这点度加不加其实都行。

那么这样呢也就ok了啊,那么其实呢还有一个什么好处,好处就是呃我们在这种模式下,你可以下面写多个方法啊,再来一个再来一个叫做second controler是吧。

s e c o d second controler,然后这块再来一个second s e c o n d c g f i r s啊。

second controller就是我们可以在这一个类里面定义多个这种方法,然后呢呃这个我们在浏览器上呢,用不同路径可以只用到不同这个方法上。

那这样的话就省就不会像我们之前定义so light那一块啊。

那么那么什么那么麻烦了哈,当然这个是一个我们的一个control层的一个定义,那么接下来我们要干的事情就是启动我们这个项目,然后呢请求我们这个my controler,请求mac trl之后呢。

看一看控制台上能不能够输出,他输他之后能不能给我们跳转到first js p啊。

到这个界面上去就可以了,那接下来就请启动我们这个项目呗,点一下这个汤姆开的九这个小绿色箭头走起,启动它。

这个日志打印可能会花一点时间。

呃默认呢也帮助我们打开了这个火狐,然后呢看这我们当前这个呃这个项目的上下文路径的是它。

那么我们要在这个路径下面写谁呢。

要访问我们这个ctrl就是当前我们项目下面这个first control。do,来把它ctrl c复制一下。

放到我们这个ui后面来,看成v诶,然后一回车你会发现成功的给我们跳到了this is first jsp。

已经成功的给我们跳到了什么,跳到这个first jsp这个位置了,然后看这这个first ctrl有没有输出位也输出了啊。

那么这样的话呢我们这个spring mvc框架的一个搭建啊,就已经简单了,这个搞定了,那我们快速回顾一下我们干了什么事儿哈,第一件事在这倒了一堆依赖啊,这对依赖呢有这个spring的一些依赖。

还有包含我们这个spring的一些a p呀,呃日志啊,哎这个loon book插件啊,嗯还有这个一些测试啊,呃这个这个等等的一些依赖,然后呢我们增加了两个依赖,一个是spring guy吧。

一个是spring gm v c,呃,这个select j a p i和j s p a p n呢,其实呢还是应该导进来,因为后面呢我们在呃写这个测试的时候,可能还会用到这两个依赖哈。

下一步是干嘛呢,下一步就是我们在这个web n f里面定义了一个前端控制器。

前端控制写法,这是固定的,就这么写就可以了呃,前端控制器里面要读一个spring mvc的一个核心配置文件的一个位置,那么这个核心配置文件放哪呢。

放到resources目录下面,我们定义那个spring mvc的x m l,在日本我们只要扫了什么。

只要扫了一下ctrl层,或者是扫描了一下,扫ctrl层就行了,只要是扫了一下这个mac rol,在my ctrl这块呢加上一个艾特ctrl一个注解,然后通过这个request mapping的。

我们指定了什么,指定了我们这个呃这个这个当前是一个呃,指定了我们当前这个处理器的一个映射路径,那好呃,那么这个是我们开发spring mvc的一个基本的一个流程就已经搞定了。

系列 3:P71:【Spring】SpringMVC_框架搭建3 - 马士兵_马小雨 - BV1zh411H79h

嗯这一小节呢我们先简单说一下这个spring mvc,它的一个呃项目搭建的时候呢,它的一些配置的一些细节问题哈,我们先说一个第一个细节问题。

就是这个dispatch so light这一块呃,在departure solar这一块就是这个里面。

那么前端控制器这块呢要默认这个初始化参数。

它要读取我们这个spring mvc点叉ml的一个这样的一个映射文件呃,那么我们说这个映射文件我们要是不通过这个引力的para,我们来配置,可不可以可以也可以,那不通过它来配置的话呢。

这个时候我们这个departure of light就会默认的干嘛呢,默认到一个指定路径下面去读取配置文件,如果如果不用什么,不用这个init pero来指定什么,指定这个spring mvc。

那sirmvc的这个配置文件的路径,然后镜那么呃那么我们这个this spiso light啊,this parture so light会自动到什么,到这个斜线web中横线inf下点找什么。

找指定的啊,指定指定名字的什么名字的这个配置文件配文件,那么这个指定的名字到底长什么样子呢,它这个配置的名字默认什么默认默认配置文件名,明白什么呢,为我们上面这个soviet name啊。

就是你这个soviet name里面写的是啥,这个标题中间写的东西是什么呢,嗯这个soviet name这个属性里面的值后面拼成一个中横线soviet,然后点叉ml会会给我们指定这样一个配置文件。

什么意思呢,就是当我们这个this part so like,没有指定我们这个配置文件到class part里面去读它的时候,它会干一个什么事呢,它会自动到web inf里面去干嘛。

去读取配置文件去那读取配置,读哪个配置键呀,它会这么读,会读你这个呃思维,like name,假设这块有新建一个xml文件,会读这个dispatch sl综合线,civili点差ml。

他会读这个配置文件里面的内容,那这个配置要放什么呀,跟他放一样就可以了,ctrl ctrl c拿过来就往这一放一粘就完事了,那么这个时候它会呃配置文件,它会进行这样的一个读取。

这个配置读取的可能这个格式是有点奇怪哈,呃后面这些都不用动,那你说这个时候他也会读取我们这个spring mvc配置念,只不过这个配置文件名它有这样一个要求啊。

读起来也是一样,但是这种方式我们推不推荐的,不太推荐不太推荐。

我们一般还是把这个推荐用这个context configuration,这个初始化参数来指定我们super mvc的一个配置线的位置哈。

那么这是一个呃这是一个呃呃dispatch select里面的东西啊,那我们试一下,看好使吧,我们再来重新部署一下这个项目呃,重新刷新一下这个项目之后呢,呃这个不用管它,重新刷新项目之后呢。

我们再来测试一下,访问我们这个first control。do,然后一回车哎,你看它也是能够访问到的,然后这块也是一个this is first jsp也搞定了。

我们看一看编译之后这个项目是不是成功编译了哈,classes,然后呢我们在这个在在在在哪,在这个target里面呃,这里面,然后哎就变成它了,在这个web inf里面。

你会发现有一个dispatch solila,dispatch sogsl的点茶面读的就是他那么好,确实也编译过来了,说明走的也是他哈,呃那么这是我们第一个配置信息,但是我们不推荐它。

我们还是使用这种就可以了,所以这种方式呢这个方式呢作为一个了解,杀了他别写了,这就完事了啊,那除了这个我们配置要简单了解以外之后呢,我们还要了解另外一个就是my control这一块,嗯。

在my control这一块呢,我们说一下这个request mapping,这个request mac是用来指定我们当前这个ctrl它的一个请求,因是路径的。

那么这个跟我们之前那个叫做at web soviet不太一样,at web so light呢你会发现它只能放到类上,如果这个i的web so light要是放到我们这个方法上的,他应该是报错的。

但是这个request mapping不一样,我们看一下这个request mapping,它能放的位置呢,既是元素类型上,也能放到方法上,也就是说什么呢。

也就是说我们这个add request mapping这一块ctrl c既可以放到z上,也可以放到我们这个啊ctrl上,那当我们在这个control上和我们这个呃在我们这个类上和这个方法上。

如果都放在这个request map之后,会发生什么事呢,当然他们两个不能写成一样卡,我写成这样,那我写成这样之后,我加了两个request making,那我在访问这个ctrl会发生什么事呢。

来我们在这块还是得刷一下这个项目来重新部署一下,呃重新部署一下之后呢,我们再来请求我们这个first control do,原因就是我们找不到这个first control点多了。

当我们在这个类上加了request map和这个方法上也加了request map之后,那么如果我们要是想请求这个处理器的话,我们在应试路径上要加上类上这个路径才可以,嗯。

然后呢再拼上我们这个呃这个方法上这个这个应收入境,那么我们在请求的时候呢,就要请求这个东西,就要在这个上面先请求什么,先请这个m s b,然后斜线下面里面这个first control。

那么也就是说当这个request map放到内存的时候,其实就是为这里面的每一个方法的上一层。

再加上一层前全运输路径啊,那我们试一试看看是不是这样的哈,呃这回再访问测试一下。

看看行不行,然后再来一回车。

我们控制台上输出了这个first controller,不是的,找到他了,因为也运行了这个first control了,出在这里了,他找了一个first。js p。

它返回的是这个first sig sp,这个first sig sp里面他没有找到,然后我们看这你看提示我什么斜线下面msb斜线m4 ,first jsp为知道为什么能找到他呢。

当我们在这个request mapping里面啊,这个在类上定义了个request mapping之后,我们这个return这块跟大家说一下,这其实就是默认在用请求转发呃。

这个return里面放的东西是什么呢,它其实就是我们这个http so light request对象,当我们return它的时候,本质上其实就是在用这个request对象调什么。

调这个get request departure,然后呢请求这个f i r s t first first。jsp,然后呢再做一个forward。

i q逗号i e s p a r a i q i e s p哈,当然i e s p我们现在还没往上写呢,呃其实本质上本质上我们return他的时候就是在干这个事儿,但是在干这个时候涉及到一个路径问题了。

就是我们这个first j s p它的路径问题,它是一个相对路径,是相对于当前这个control当前这个方法的路径啊,那么在这个路径下面去找这个first js p,但当前方法这个路径在哪,在哪里面。

在这个msb下面,说白了你当return这个first jsp的时候呢,其实就是请求转发给什么呢,转发给m sb下面一个first gsp啊,所以这是一个路径问题哈,但这块如果我们要写成这样一个斜线呢。

它就在每个绝对路径了,那或者是一个基准路径了,他会以什么呢,他就跟这这个时候再请求在这个跳转路径时候就跟他没关系了,固定往哪跳啊,固定在当前项目下,就是我们当前这个外bp下面往下走,再往下走。

我下面的哪一个下面这个first js p,那这个时候跟上面这个路径啊就没关系了,就不会参照这个路径来来调整它了,这个呢我们在java e那块讲过这个呃,这个什么就是请求转发和响应重定向的一个路径问题。

那么跟那个是一样的哈,我们把它改一下之后呢,我们再来测试一下,看看行不行哈。

好部署完毕,部署完毕之后呢,我们再来来在这儿再来一刷新。

ok没问题就过来了,那么这是一个呃关于这个呃control里面的第二个参数的一个,这个这个处理也就搞定了,呃搞定之后呢,接下来我们说第三个参数处理啊,第三个参数理这块呢。

假设我们这里面有一个什么这里面呃,我们的页面为了安全考虑,我统统都不放在这儿了,我放哪儿呢,我放到web inf里面,我创建一个什么,创建一个叫做v i e w v5 的一个这个在web inf里面。

我创建一个v5 层,然后呢我把这个first这个first gp我放这了,我把这个first gsp,我放view这块放这里,ok就完事了,都挪过去呃,挪过去之后呢。

那么呃这个时候哈呃我们要是想请求转发的这个first js就该怎么写呢,在这个web中横线inf下面这个first jsp就可以了,呃那么这个请求转发也是可以请求转发到这个web i f幕下面的。

那这个时候我们再来测试一下,看看行不行哈,这个应该也是没问题的。

没问题之后呢,我们再来在这块再测试一下,一回车诶,找不到了啊。

web i f e web i f下面一个少了一层,这边还有个view呢,这边还少了一个view层斜线v i e w不定还有一层这样的目录是吧。

嗯再来重新部署一下。

ok刷新完毕了一回车诶,也找到了,那找到之后哈。

那假设我后面的每个页面我都想往这个web web inf里面呃,放,你会发现这个东西特别特别什么特别特别难受,就是我每次返回界面的时候,都要加上前面这一串。

而且呢假设我的这个每个这个js p呢都是每个页面都是点jsp的,我后面还要加上一个什么,加上一个点j s p,这样会比较麻烦,那我能不能在这块把这个路径简化一下呢,可以简化一下。

在简化的时候呢,我们需要配置这个东西叫做呃叫做什么,叫做我们这个叫做视图解析器。

这个视图解析器是个什么意思呢,这个跟什么呢,这个跟我们这个还是跟我们这个sprm mc执行流程相关呃。

前端控制器呢通过处理器映射器找到了什么,找到了我们自己的这个处理器,我们自己处理器是啥,自己处理器就是我们自己处理那个control是谁呢,其实说白了哈,这个我们现在还没看到,没看到没关系。

通过前端控制器,假设现在找到了,找到了我们自己的处理器了,那处理器是谁呀。

自己这个处理器就是它嗯,就是我们在这块写的这个代码,它就是我们自己定义的一个处理器,然后处理器返回这个字符串之后呢。

谁给我解析这个字符串并跳转页面呢,是这样的,他把这个路径返回之后哈,继续向上返回,会给一个这个视图解析器,由视图解析器来解析我们返回那个字符串一个路径,然后他解析完之后呢。

由他来给我们帮助跳转到那个页面去啊,跳到那个页面去,那么我们可以通过配置视图解析器来简化什么的,简化我们返回一个路径啊,那怎么配置呢,是这样的呃。

我们需要在这个呃在我们这个spring mvc这个xml中配置一个视图解析器,配置一个这个视图解析器解析器,那这个解析是怎么配置的,就是一个b吗,非常简单。

这个class叫做呃internal i n t e r n l internal呃,resource view resolar,就是它默认的一个视图解析器,在这个配置视图解析器的时候呢。

我们可以指定路径的前缀和后缀,指定指定路径的这个前缀和后缀哎,通过一个叫做props属性,叫做prefix啊,就是指定前缀,还有一个叫做诶,还有个什么,还有一个就是哦哟。

还有一个是property a property,通过他的一个surface来干嘛呢,来指定这个后缀,然后呢分别给定value值,然后给定这个value值v l v l u e v60 哈等于。

那么这个prefix和surface怎么指定呢,假设我们这个control想往往这个web n f里面这个view里面去跳转,访问这里面界面,这里面假设有十个界面啊,但是访问哪个不一定。

但是我可以肯定的是什么呢,肯定的一定是y不按f v里面的东西,同时呢这个view里面放的一定是js p,那也就是说我们整个这个路径里面,其中前面这一部分已经固定了,后面这一部分已经固定了。

唯一变化的就是这个first,那好我可以把这个固定的内容给它配置到视图解析器里面去,在视图解析器里面,在解析这个路径的时候,自动在我们返回的这个基础上呢,给我们拼一个前缀和拼一个后缀,那拼的前缀是谁呢。

就是他注意啊,来ctrl c复制一下,ctrl x剪切一下吧,哈放到我们这个前缀上去,注意以斜线为开头,以前为结尾,不要丢哈,那么在什么呢,在我们这个呃点j s p这块的后缀这块,我们配置什么。

配这个点js p呃,在这个这里面这个它当我们把这个视图解析器的前缀,配后缀和配置好之后呢,那我们ctrl层只要返回我们这个文件名就可以了,那么它会自动在这个文件名前面拼什么呢。

在这个文件名前面拼这个前缀,然后自动这个上面在这个后面拼这个后缀啊,那我们这个ctrl层这块呢法东西会简单一点,只要写对应的这个文件名,不带透视名就简单多了,ok了,那这样ok吗啊,我们来测试一下。

重新部署一下。

好部署完毕之后呢。

我们再来访问我们这个first control do,然后呢再来一回车,ok它也是可以正常的跳转过来的。

那么这块呢简单的给大家解释一下这个视图解析器哈,就是说一下这个配置。

当然这个呃spring mvc这个执行流程,我们后面会给大家再稍稍细致一点讲哈,那只不过呢我们在第一次测试super mvc这块呢,我们把这个这个呃大家目前能够了解到的一些配置呢跟大家说一下哈。

嗯那哎呦谢谢哈。

系列 3:P72:【Spring】SpringMVC_执行流程和三大组件 - 马士兵_马小雨 - BV1zh411H79h

这节课呢我们给大家讲一下这个spring mvc这个框架,它的一个执行流程,以及它的一些组件,还有它相关的一些啊,这个静态资源处理和放行的一些东西给大家总结一下哈。

嗯那么我们之前呢在测试这个spring mvc的时候呢,我们是在这准备了一个ctrl,呃因为在这块扫描ctrl层的话呢,这里面其实在mvc模式下,在我们整个项目里面不光有这个ctrl这一层。

那么在我们这里面可能还有什么还能有这个嗯,com。m s b。s e r v s c service层,后续呢可能这里面还有什么呢,还有这个呃我们这个dio啊,或者是我们结合my bt之后。

这里面还有一个map,那么我们这个呃mvc这块需要扫那一层的,它需要只需要扫ctrl层就可以了,所以暂时这个map和service这一块呢我们不扫也行,所以这块我们可以把它改成soctrl也行的啊。

那么呃我们之前的代码呢是在这个control层里面呢,我们准备了一个control这块我写成一个普通的class,假设叫做my c o n t r o uo t i o cler。

呃,然后呢呃加上一个at controler的一个注解,那在这里面呢我们再来一个哎,public返回值为string,然后起个名字叫做呃test呃,test一这的一个方法。

那在这块呢我return一个这个什么return一个这个界面的一个路径,例如我这块写成一个s u c c e s s success,那么要想返回它的话呢,我们需要在这个web app下面呢准备一个呃。

之前呢我是把这个页面放到了web i f里面,我在这边准备一个v i e w的一个一个目录,然后在这个目录里面呢,我们准备一个success的一个页面,s u c c e s s success。

点js p,然后呢在这块写成一句叫做呃呃this is s u c c e s success啊,这个page啊,那么我们准备占一页,那如果说我在control层要是想往这块跳的话呢。

我们直接return一个success就可以了。

但是这里面有个什么东西,我们需要配置呢,需要在这配置一个视图解析器啊,需要一个视图解析器,这个视图解析器呢可以呢。

呃可以呢,其实我们不需要输入解析器,我们在这块这么写也行y吧,这个我们之前也讲过哈,a n f写信下面这个v w v w里面这个success。jsp,我们写它这个完整的路径也可以。

但是通过视图解析器呢,我们可以在这块定义这个它的一个前缀和后缀,那么这个叫做呃b然后呢它的这个class class叫做呃internal internal resolve。

an internal resource resolve。

这是一个视图解析器,然后呢我们在这里面呃配置了这样几个属性,一个是a property,一个叫做pre prefix,嗯,然后呢通过这个value属性去给它指定吧,写成一个呃写成一个斜线。

y中横线i n f里面的这个v i e w和v5 啊,不要忘了一个斜线哈,还有一个是这个叫做surface surface x的一个属性s u surface x。

然后呢这块呢我们放了一个啊这个点g s p。

那么我们配置了视图解析器之后呢,它就可以在我们这个返回的这个路径之上呢,我们只要返回这个文件名就可以了,它就会在我们这个文件的路径之上呢,自动补充一个前缀和后缀了。

在这块再加上一个at request mapping,然后呢这块呢给他来一个map吧,谢谢my c o n。do,其实呢我们在request map这块呢,这个后续再讲吧,前面这个斜线加不加都行。

但是我暂时呢我还是先跟我之前这个思维来写法的,保持一致哈,先给它加上呃,那么我们先来启动项目是吧,启动项目之后,我们请求这个my controler,然后跳转到我们这个success or jsp。

那么我们接下来给大家分析一下,就是诶这个请求以及跳转这一块这个过程啊,他都发生了什么事,他都有哪些环节需要我们去这个呃,注意一下,说一下他这个spring mvc,它的一个执行流程,这个应该已经。

好浏览器的已经帮我们帮我们打开了。

打开之后呢,因为它默认帮助我们访问这个index嗯,index jsp,但是这个index jsp呢,呃js p呢在我刚才已经在这里把这个index jsp已经删掉了,没关系啊,我们直接访问什么。

直接访问这个做嗯,my c o n。do一回事。

哎他就跳了这个success成功这个页了,这是我们之前的操作哈。

那我们就分析一下,当我们请求这个ctrl的时候,然后呢请求他然后一跳转之后呢。

这个过程啊发生了什么事呃,在这块呢通过一个时序图的形式来给大家分析一下,就当我们tom开始启动以及请求完成响应这一块都发生哪些事情,这个时序图是这么看,这是我们整个的这个程序在往前走的时候。

它的一个运行环境和各个环节在什么时间发生了什么事,当我们项目一启动的时候,发生了一个什么事呢,就是我们的tom看着一启动,它会加载这个web。xml这个文件,一加载这个web。xml文件呢。

它会初始化呃,实力并实例化并初始化这里面所定义的这个so light,然后呢在扫描这个web的差别的时候呢,就会发现这里面有个什么,有个dispatch soviet。

就会把这个dispatch soviet进行一个初始化,初始化之后呢,呃那么他也会呃也会通过这个spring mvc点叉ml配置文件来创建什么,来创建spring容器,然后再根据那个我们的一些注解容器。

我们初中嗯初始化我们容器中的一些对象,那这个是在我们正式发生请求之前,那么唐门开始启动所发生的一个事情,那整个过程是由tom cat读取web的插苗,然后呢在初始化dispatch soviet。

然后再进行一个spring容器以及spring容器扫描ctrl层,促使我们的ctrl这样一些的操作之后呢,我们用户这块呢啊就发生了一次请求,这一次请求的时候呢,先经过tom cat。

然后tom cat根据我们的请求路径呢,它会先到达我们这个前端控制器,就是我们这个dispatchet,因为在dispatch soviet里面呢,我们配置这个路径是一个斜线。

那么这一个斜线它的作用是什么,是拦截除gsp以外的所有的请求,都会经过这个departure so that,然后呢请求到达这个dispatch撕下来之后呢,这个dispatch搜过来的就会干嘛呢。

就会解析啊,就会帮助我们解析什么,解析我们这个请求路径对应的是哪个control,然后在对应ctrl的时候呢,就找到了什么,就知道我们自己定义的这个mac ctrl啊。

就是我们在这个dpture so light这一块呃,我们的请求到了这个呃,到了我们这个tom开了之后,tom cat根据这块的这个呃这块可以先这个可以先哦删掉哈,这个是我们后需要玩一个事情哈。

呃我们的this party,我们的请求到达了我们这个tom开了之后呢。

呃根据这个运输路径就匹配到了我们这个dispatchet。

然后我们的departure soviet呢会根据我们在这块请求的这些参数,然后请求在上升到ul进行解析。

解析完之后呢,我们发现这个ul定的是谁呢,对应的就是我们这个my controller。

对应的就是这个方法,那么这个时候呢就会执行这个方法,在执行这个方法之后呢。

他return一个success,那么这个success就是对应了什么呀,对应了啊,对应了我们的一个呃,就是在运行这个control的时候呢,对应了我们这个路径。

然后对应到我们这个success jsp,那我这个时候呢就会把success or js p呢响应给什么,响应给我们的一个用户,那么这个整个就是它的一个呃时序图,那么有了这个一个时序图之后呢。

我们说在这个发生的这个在时序图上所发生的各个事件,那么呃都是哪些,都是spring mvc中哪些组件,哪些东西来帮助我们完成的,那接下来呢我们就说一下这个supreme m v c啊。

它的一个执行的一个原理,这个上面是执行的时序图,而下面这个是它的一个执行原理图,注意下面这个不是时序图哈,这个只是一个逻辑图,当我们的用户请求啊,请求到达了我们这个前端控制器之后,这个前端控制器啊。

就好比是什么,就好比是一个公司的一个呃这个什么主控,就好比是一个公司的主控或者是一个控制中心,控制中心由它控制着我们整个super mc它的一个交互啊,那么有了这个也就是说我们请求先到达这个主控之后呢。

他干了一个什么事呢,他先解析这个路径,解析这个路径之后呢,他自己解析吗,他自己解析可能太麻烦了,他下面有个小弟,第一个小弟叫做处理器映射器,处理信息测器是干嘛的呢。

他就把这个路径或者把这个u r l或者把这个请求给他给他之后呢,由这个处理器映射器通过解析我们的路径,给我们返回什么呀,给我们返回对应的这个controller,嗯。

对的这个control就说白了说白了我们这个前端控制器在找什么呀。

前端控制器嗯,在在在在在这里我们这里面配置的前端控制器,它是如何找到我们这个呃control里面这个这个这个处理单元,它并不是自己直接来制造的,它是有个叫什么,有个叫做呃处理器映射器的一个组件。

他要通过这个组件来帮助我们找到什么,来帮助我们找到我们自己定义的roller controler啊,在哪里找到之后呢,他把这个control给给再返回什么,再返回给我们这个前端控制器。

返回给前端控制器之后,前端控制器在这块直接调用ctrl的方法吗,是不是这样呢,是不是在前端控制器里面直接调用我们这个方法进行运行呢,也不是,为什么也不是呢,因为我们再往后学啊,我们这就会大家就会知道了。

就是这个ctrl这一块啊,这这个参数列表是可以变化的,是可以多种多样的,返回类型也是可以多种多样的啊,呃你可能我们需要把什么,需要把请求的参数往这放,需要把这个结果呢进行解析等等啊。

封装参数和解析这个过程呢,是不是要让我们的这个前端控制器是不是要让他来执行呢。

也不是的,那么前端控制器呢说要是找到了对应这个ctrl之后,这个ctrl就是它就是我们定义的handler呃,我们的这个定义的这个自己定的那个呃处理请求的那个ctrl层的方法。

其实就是对应我们这个处理器,就是它呃,那么我们处理汽车器呢已经告诉前端控制器了,你的处理器在这里呢,那你直接调用这个处理器吗,我们的前端控制器是直接调用这个处理器吗,不是的,也不是的。

它要通过一个处理器适配器来调用我们这个处理器,什么叫适配器呢,这个适配器能给简历给大家翻译一下,就举个例子,就像我们的电脑是19伏的,但是我们查的电源是220伏的,我们要把这个19伏呢。

28 20伏能转换成19伏对吧,一样的,那么同样的我们前端控制器这块呢,如果是自己调用这个处理器,自己调用我们的ctrl里面的方法,那需要我们在这自己做这种方,做什么,做这个参数的处理啊。

返回值的处理啊啊等等一系列的东西比较麻烦,那怎么办呢,那么前端控制器这块呢也不是直接调用处理器,它是先干嘛呢,它是通过这个组件叫做处理器适配器,他告诉处理器设备区t去干嘛,你去给我执行这个呃。

这个去调用这个方法去,调用完之后呢,你把这个结果,处理器适配器会把请求中的参数给我们放到我们的ctrl之中,同时呢再把这个结果放到这个model and wave当中,给我们干嘛呢,给我们返回呃。

所以是有一个什么有一个中间商,那么这个东西就叫做处理器适配器。

那么我们这个处理器是谁,处理器已经说了,这个处理器其实就是我们在这所定义的一个什么呢。

就是我们的ctrl的一个代码,就是我们这一个处理单元,那这个数据单元啊,那好那么当我们这个处理器通我们的前端控制器,通过处理器适配器调用完我们的处理单元之后呢,我的处理器适配器会把这个结果呀返回什么。

会给我们返回我们的前端控制器,返回阶段控制器的时候呢,需要传递的参数呢都给它放到这个model and wave这个对象里面去,那可能说老师我没有看到这个对象,这是在底层源码的时候能进行这么一个封装。

当然我们也可以直接返回正对象,也是ok的,那么这个model view返回之后呢,那么这个时候前端控制器就会看是吧,这个model view里面有没有跳转的页面和一个数据,有有的话的时候。

前端控制器是直接控制页面跳转吗,不是的,他假设想控制页面跳转的话呢,它也不是自己直接干这个活,他再交给什么,交给自己的第三个小弟,第三个小弟就是一个视图解析器,把这个末端的wave呢。

把这个wave试图给你挤到这里面来,就是我们的什么,就是我要页面跳转的一个路径,例如把这个success信息,s u c c e s s success信息给你放到视图解析器里。

视图解析器呢会通过会处理这个我们的一个视图的路径,然后呢给你给我们返回一个view对象,那这个view对象里面就带着什么,就带着我们的一个试图的一个信息了,但这个视图信息之后呢。

那么前端控制器获得这个视图信息,再把什么呢,再把这个数据给我们的一个视图层,在视图层再进行渲染,怎么渲染呢,例如用jsp技术把数据展示出来,或者用free marker技术哎。

网页静态化技术把这个视图展现出来,展现出来之后,那么这个视图准备好了,再告诉前端控制器,视图已经准备好了,准备好之后呢,这时候前端控制器再把这个视图里面那些信息的响应个什么,相应给我们的用户啊。

那这个就是我们整个spring mvc它的一个执行流程,那那么执行流程这一块呢,可能大家还是稍微的第一次接触,可能还是稍稍有点蒙圈,没关系,再大家整理一遍哈,用户请求过来之后,他肯定是又通过一个ul啊。

那然后到达我们的前端控制器了,前端控制器呢如何找到我们对应的这个ctrl处理单元呢,他自己不找,他交给我们这个处理器映射器去找,找完之后呢,他把这个处理器映射器呢,把我们处理单元给我们返回之后呢。

那他自己直接调这个处理单元吗,也不是他在通过第二个小弟处理器适配器,让他去这个调用处理器的里面的一些方法,我们处理单元的一些方法返回结果之后呢,在这个处理器适配器把这个结果返回给我们的前端控制器。

前端控制器拿到结果之后,直接控制页面跳转和做数据展示吗,不是再把这个页面信息交给视图解析器,解析完视图之后,由视图解析器在正式的返回啊,要跳转的视图是哪一个视图,哪一个拿到之后呢。

前端控制器要直接把这个数据进行渲染吗,也不是他再把数据交给什么,交给视图层,视图层进行渲染就可以了,但是视图层这个渲染这一块呢啊就是我们前端的一些事情了啊,是渲染完之后呢。

前端控制器的告诉我们的这个用户啊,就是你可以有这样一个响应啊,可以做出响应了,你可以拿到什么样的一个数据了,那么这个就是整个的一个spring mvc的一个执行流程呃。

在spring mvc这个执行流程这一块呢,大家一定要注意这样啊这样的一个这个面试题啊。

就是呃supreme vc这块呢它也会有这样一个面试题。

就是问一下这个spring mvc的这个组件,也就是三大组成部分啊,或者三大控制。

三大组成部分分别是哪些呢,是这一部分一个叫做处理器映射器,帮助我们找我们的处理单元的一个叫做处理器适配器,处理器适配器呢是帮助我们调用啊,这个我们处理单元方法的,第三个呢是我们的视图解析器。

这个视图解析器呢是帮助我们处理视图解析的啊,那么这个是也是我们spring mvc的,叫做三大组件,大家一定要记住哈,这三大组件的名称一定要记住,分别是处理器,映射器,处理器适配器和视图解析器。

那你可能说这里面还缺了一个前端控制器,这个前端控制器可以说是我们spring mvc的一个核心的一个组件,它是做一个主控主要的控制中心,在这个主要控制中心下面有三个组件。

那么这三个组件呢呃spring mvc呢其实已经给我们默认配置好了。

这三个组件其实是我们可以自己指定的哈。

再来看一下前端控制器,我们说了呃,handler mapping就是我们的处理器映射器,handler就是我们的处理器,它其实就是我们自己定义的ctrl代码,就是我们自己定义的什么自己定义的。

嗯ctrl层的这个叫做ctrl这个处理单元哎,所以单元啊三大组件里面有没有这个处理器的没有,因为这个处理器是我们自己定义的,三大组件,分别是处理器,这个给你标一下,还有一个是我们的一个叫做处理器适配器。

还有一个就是我们的这个视图解析器叫做will resoler。

呃,那么呃为什么要用处理器适配器去调用我们这个自己的处理单元呢,要原因就是呃这个我们呃我们这个处理器里面。

还将来可能在里面会写不同的参数啊,这里面可能会写不同参数,然后呢会有不同的返回值进行处理。

那么这些处理的话呢全交给谁来做呢,全交给我们这个处理器适配器来做,那么这边都是一个usb,就相当于对应对接着我们这this partisweet,而这边不同的结果呢相当于对应我们不同的这个韩德尔。

它的一些特征呢,通过这个处理器适配器呢去给我们调试就可以了。

最终走到这个view resolver这一块呢,view resolar啊会给我们生成v无视的对象,然后呢对view对象进行渲染之后。

再将信息返回的用户对,然后第六部分这个视图层,视图层这块呢就这个技术其实就是偏前端一点的技术了,那么我们在这个呃spring mvc中的。

正常来说应该是配置一下什么呢,应该是配置一下处理器,映射器,处理器适配器和这个视图解析器的呃,但是目前来看我们发现我们只配置了这个视图解析器,在配置视图解析器的时候呢。

呃省配置视图视图解析器是怎么配置呢,就是在这儿配置的,在这个spring mvc点叉ml里面。

我们在这配置了一个视图解析器,配置完视图解析器之后呢,可以通过视图解析来指定我们跳转路径的前缀和后缀,以简化我们可除了层返回的这个信息的这个路径的一个,编写的一个写法呃,正常来说我们应该干嘛呢。

应该在这个spring mvc中配置三个什么,配置三大组件,这三大组件分别是什么呢,分别是配置配置,配置处理器,配置处理器映射器,还要配置一个什么呢,还要配置一个处理器适配器,但是别信。

但是呢嗯我们要是不配置的话呢,目前来看这个代码测试似乎也是好用的,但是事实上呢我们还是要在这配置一下的,为什么要在这配置一下呢,主要是不配置这个处理器映射器和这个处理器适配器的话。

那我们后期呃在这个control层接收参数以及返回数据这块呢。

可能会存在存在问题,所以呢我们还是需要配置一下的。

你怎么配置呢,这个东西是这么配置的啊,可以给大家这个在我们文章已经写了哈。

怎么配置,是这样的,这个这的这个hler mapping的实现类的作用是什么。

实验类的作用就是它是帮助我们处理这个request mapping这个注解,所以呢实现类是这叫做request making handler mapping。

我们要在我们的这个哦这个spring mc中的配置一下这个处理器映射器,然后用这个类就可以了。

应该怎么写呢,是这样写的哈,其实就是说明一个b非常简单,说明一个b,然后呢指定这个class。

为什么这个class class为我们的这个叫做在这呢叫做request mapping。

hla ma,你这有点长啊,e q r e q e request making,emp,然后看到了卖屏,那么这就是配置我们这个处理器映射器,除了处理器映射器外,还有叫做处理器适配器。

这个适配叫做request main handler adapter,a d a p a t e r啊,那这就是配置我们的处理器映射器和处理器适配器,那么spring默认给我们不写的话。

spring其实也给我们配置了两个默认的,但是这两个默认的呢其实没有这两个好啊,这两个呢相对来说比较好一点哈,那么配配它之后可能会让我们这个三大组件就已经配置齐全了。

但是呢这两个东西看起来似乎这么配置稍微有点繁琐,我们可以用一个什么注解来给它简化呢,用一个annotation driven的一个注解来给它简化一下,怎么写呢。

用的是我们这个叫做呃尖角号mvc mvc的一个呃vc的一个标签,但是目前这里面这个mv c标签用不了,为啥用不了呢,我们名称空间里面好像没有mvc呢,我们把这个复制一行,给他来一个mvc。

然后呢把这两个也给它复制两行,把这个mvc的这个这个名称空间都给他加上哈,呃t所有的tx改成mvc啊,这个地方也给它改成m v c。

这个地方给它改成mvc,那么改成mvc之后呢,我们就在这块就可以用这样一个注解叫做m v c冒号叫做annotation driven,呃,加上这个诶,怎么变成tx了。

我上面应该是配错了是吗。

哦这块还没有改呢,这块也得改成一个mv c啊,那这回就对了,mvc annotation driven,然后呢这个是一个可以写成书面签,当然也可以形成一个单标签就可以了,那么这个其实就是什么。

其实这个叫做开启mvc的注解,这个作用叫做开启mc的,这个叫做注解驱动,开启开启,mvc注解驱动,但是在开启mvc注解驱动的时候呢,呃那么它会自动干嘛呢,自动给我们给我们配置好什么。

配置好这个处理器映射器和处理器处理器适配器,啊适配器,所以呢我们在使用mvc的时候。

一定还是要把这个加成下来,加上下之后呢,就默认给我们配置了,省得我们自己在写这么两行比较麻烦是吧。

那么三大组件的一个配置呢,在这块儿呢也跟大家说一下哈。

那么当配置了mvc annotation driver后,其实说白了就是把这两个处理器映射器和处理器适配器配置了之后。

那么啊我们后续呢这个像接收返回的json数据啦,啊参数验证啊,还有统一一些异常灯的一些功能才能够正式的生效和使用。

所以呢这个三大组件的一个配置这块呢。

系列 3:P73:【Spring】SpringMVC_静态资源放行 - 马士兵_马小雨 - BV1zh411H79h

好三大组件配置完毕之后呢,接下来呢我们接下来呢,我们给大家讲一个叫做呃,spring mvc里面的一个静态资源放行呃,那么呃这个静态资源放行是个什么意思呢。

我们通过一个界面给大家来展示一下吧,哈举这个例子哈,我们在这个web app里面呢,我们准备点静态资源呃,什么叫静态资源呢,这块呢相信已经不会跟大家解释了,就像说我们的一些css文件,js文件。

还有一些图片啦,嗯还有一些其他乱七八糟的,就是保持不变不动的一些资源,我们管它叫做静态资源,那么一般呢在我们这个s s m项目中呢,我们在web app里面呢,我们可以准备一个这个目录。

准备一个js目录,这里面专门放一些js文件,然后在这呢再准备个什么,再准备一个呃i m g目录里,然后里面专门放这个图片文件呃,然后里面再准备个什么,再准备一个叫做嗯,还有一个是我们的一个叫做呃cs啊。

例如网址里面放一些css文件,我们就以这三个来举例哈,呃那么我们在外边a p p a p p下面呢,我们在准备什么,再准备一个呃g s p的一个文件,j s p和html其实都都可以哈,那我们来试一下。

我就把这个index index index呃,第二这sp呢我们再给他准备回来吧,哈刚才一不小心我给它删掉了,那删掉之后呢,我们在这块呢做这样一个事,就是我想往这个cs s g s和这个i m g。

里面的放任的资源哈,例如在cs目录里面呢,我创建一个文件叫做aaa啊,dcs s的一个文件,那么暂时让这个文件空就可以了,因为我们不需要让这个,我们只要是测试一下,这个能不能获取这个文件。

而不是说这个呃要让它有什么功能啊,然后呢在这个i m g里面呢。

我们再准备一个图片,这个图片呢我们可以做个截图。

我们把这个呢给大家截一下吧,然后接一下这个公司的一个logo啊,保存一下,扔到桌面上来一个logo呃。

那这个桌面上多了一个logo之后呢。

我们要把它放到我们这个项目里呢,这个其实也好办啊,把它来ctrl c复制一下,扔到这ctrl v这一粘就可以了,粘回来之后这个图片可以不要了。

js文件呢,我们随便在这块再new一个。

这个文件就可以了,例如我们管它叫做a a a啊,叫做b b b bbb。

点这个gs吧,那这样的一个文件,那么假设我们在这个页面上呢,我们需要这三个静态资源呢,怎么需要呢,假设导图片怎么导呢,正好我们可以来个i m g的一个标签,来一个s r c属性的导入,我们这个图片。

它是我们i m g里面的一个logo,点png的一个图片导进来就可以了,那如果说我想找一下这个css样式文件,我该怎么导呢,在这里面呢,我们可能要通过一个这个link标签。

然后有个ie l为style sheets,然后它的这个叫做呃type为a text css,然后写上它的一个h r e f或f,指向cs目录下面一个叫做a a a。css文件。

那假设我想引入这个js文件,我该怎么引入这个bbb的js,我该怎么引入呢,怎么引入,再来一个script,然后再来一个s r c等于什么,等于这个js目录下面的一个,这个叫做b b b。js一个文件。

那么好,那么这个就是一个呃一个页面,它引入了什么,引入了这么多资源,那引入了这么多资源之后,我们测试一下,看看这个index jsp在请求,我们在请求这个index jsp的时候呢。

它会不会能不能够成功地加载这些资源哈。

那么我们在这块呢需要做这样一个事,第一件事呢我们需要呃,在这块呢应该重启一下重点,这个重启一下也不用重启啊,在这块up to the classes and resources。

就是更新一下,我这个字节码和这个相对应的资源,要不然的话呢我们在这更新那些资源,可能会呃,没有成功的编译进,我们这个这个这个target的目录哈,这是一个,然后呢在这块再点一下它吧。

啊再重新相当于重新部署一下是吧。

部署一下,部署完之后呢,我们在这个浏览器上请求一下,只能请求一下我们这个index js p i n d x,index jsp,在请求index jsp的时候呢。

我们测试一下吧,在这块呢为了验证已经请求他了,我们在这块写这个代码叫做this is an index,点g s p,一会儿出现这个文字,就说明确实请求到他了哈,那么我们在请求之前呢。

我们在这块儿用打开f 12,然后找到这个网络,然后我们测试一下,看看它一共发生了几次请求哈,然后再来一回车,我们发现this is index jsp,确实是找到我们当前这个jsp页面了。

但是你会发现后面这个图片它就显示不了,这个图片显示不了,我们发现这里面有有多少呢,你当他不存在就完事了,因为这个这个东西呢我们之前测试过这个,这个就当它没有,就当它不存在哈,那么下面多了什么。

三个4404分别是指向哪一个没找到呢,是分别是这个a a a。cs没找到,还有这个bbb。js没找到,还有这个logo。png没找到,诶,他为什么会找不到这些东西呢。

原因是这样的哈,原因是这样的,首先呢我们总结一下。

我们说一下,就当我们请求这个index jsp的时候,发生了一个什么事情哈,给大家画个图解释一下。

嗯,在在在在这呃,那么我们的程序这块呢,有一个叫做呃呃这个叫做dispatch solid,i s p a t departure soviet,它是一个我们的前端控制器。

当我们第一次请求这个index jsp的时候,那我们在这请求这个i n d x index,点j s p的时候,那么就像我们的这个tom cat呢,发送了一个请求,嗯,发送了一个请求。

但是这个请求会不会,我被我们这个dispatch soviet拦截呢。

并不会,因为这个dispatch the light,这块的主要拦截谁呢,主要主要匹配的就是我们这个呃,注意看他这个配置信息主要是一个斜线。

而我们此时恰恰请的是一个index jsp,所以这个时候并没有走这个dispatcher来,而是直接干嘛呢,是直接访问到了我们项目下面的一个index,jsp,直接访问到他了。

i n d s index。js p访问到它之后呢,我们tom cat就会把什么,就会把这个index js p呢,返回给我们的浏览器啊,那再加上这一段就是我们的一个浏览器啊,这个就是我们一个浏览器哈。

浏览器拿到这个index jsp的时候呢,就会进行一个解析,拿到这个文件就会解析,解析完之后干嘛呢,解析完之后当然就要进行展示了,对不对,在解析的时候呢,他发现这里面还需要向服务器啊,加载三个资源啊。

解析时在解析时啊,这个发现什么呀,发现需要啊,需要像什么,像这个呃这个服务器啊获取什么呀,像服务器来获取获取三个这个资源,这三个资源分别什么呢,分别就是我们程序里面这个a a a。cs。

还有一个是这个b b b哎,点j s,还有一个是我们的一个叫做logo呃,logo点这个i m g,那logo。一个点点png,好像是啊,这个图片拓展没用,好像忘了,没关系啊。

反正就是需要加载这三个资源,那家里三个资源怎么加载呢,那我们的浏览器会默认,再次产生三个请求啊,产生三个请求,这三个请求分别是一个哎两个三个,这三个请求分别对应的是谁呢。

分别对应的就是我们下面所要这个请求的,三个资源,那他要请求谁呀,他要请求我们这个a a a。c s s,然后下面这个请求我就是b b b。j s,下面请求又要请求我们这个logo。

要请求我们这个logo,哎呀哎呀这个怎么给搞到下面去了,请求这个lg有logo啊,点png来请求他,那么这三次请求,会不会被我们的departure soviet所拦截,当中会被拦截到。

因为我们这个departure soviet里面,拦截拦截的一个路径是这种规则,是一个实现的一个规则,那这个时候这三期三次请求,就会被我们的this partisol e所拦截到,那拦截到之后呢。

它就会解析这些路径,而这个this party sweet它是干嘛的呢,它是专门给我们找什么,找我们的controller的c o n t r o l e r的,它会不会到我们的页面下面。

去找这些相应的文件呢,不会找,那不会涨,所以呢这个时候departure so来,就会发现,在control里面有没有对应这请求的映射路径的,一些对应的control啊,没有,那没有的时候呢。

有我们这个this is parser。

我们在这所看到的这三次请求,三个4。4,然后呢我们可以看一下他是怎么请求的哈,在这呢我们可以点开它请求的应输入径,是我们当前项目下这个cs目录里面,这个a a a。c s s。

其实这个东西如果说我们要是直接访问,也是访问不到的,我们可以试一下,来给他ctrl把这个路径来ctrl c复制一下,拿到这来,没找到的,那那为什么呢,因为这个路径会被我们的diator sweet拦截。

然后呢,他在自己的ctrl里面呢,又没有找到对应的一个映射文件,那么其实我们要是想让这个东西能够找到,该怎么办呢,我们应该告诉spring mvc。

或者是告诉谁呢,或者是告诉我们这个dispatch the light啊,告诉什么呀,告诉我,如果他请求的是这个a a。cs,或者是b b b。js,或者是这个logo。p n g,它属于静态资源。

你不要给我去匹配control群,你直接给我放行,让他到我当前项目里面去找就可以了,那么这个动作呢就叫做静态资源放行。

那静态资源放行这块该怎么配置呢,是这么配置的哈。

在我们这个spring mvc之中,在这个spring mvc这个点差ml之中,在这块继续往下配置一个什么配置,一个叫做配置配置,静态资源放行,静态资源放行的这个方式,是用这样来放行的一个mvc啊。

冒号叫做什么,叫做resources,这个resources呢,就是我们的一个静态资源的一个路径,和一个什么和一个映射关系,那这里面分别有一个map属性,和一个location属性,分别是什么意思呢。

mapping指的就是我们这个a p p i n g,mapping,指的就是我们这个u r l中,url中的这个路径呃路径,然后这个l o c t o location,指的是什么意思呢。

指的就是这个对应的路径到什么呀,到项目中哪个哪个文件夹中,哪个目录中去找对应的什么对应的资源,那么这个mac这块我们该写什么呢,这个写法是这样的哈。

我在笔记上头已经准备好了,是分别是这么写这么写这么写,这么写什么意思呢。

哎这个map这块跟谁对应的,跟我们这个这块对应的哈。

来看这我们这三次请求看一看,它分别请求的都是js b b b。js,然后呢这块事情是i m g logo。png,其实我们说哈这个将来呢。

我们在这个cs目录里面,还有在这个i m g里面啊,还有这个js里面的,可能里面会有很多很多的精神资源,那我不能一个一个的文件去放行啊,那怎么放行呢,我们发现如果请求映射路径中,如果带上cs了。

如果带上这个i m g了,如果带个什么呀,如果带上这个gs了,我不管这个请求意识路径后面是什么,后面是什么,我都认为这是在访问静态资源,而如果我的请求路径后面是这样的,就代表它是静态资源了。

那么怎么写呢。

这么写啊,怎么写,这个参照这个语法器就可以了,斜线js斜线星星什么意思。

斜线gs啊,gs gs斜线星星,意思就是当我的请求应试录取中,而且gs这一段后面呢有可能是多层的,有可能是单层的多少层,咱们还不确定,因为这个js里面万一有子目录怎么办,对不对,那我这会就写两个星。

两个星的意思就是js下面啊,无论这个ul路径,js这一层后面可能有多层,多多多多少层,没关系,那如果他请求是这个资源,我就把这个路径,我就把这个路径呢给你映射哪里呢,映射到我当前当前项目下面。

这个js目录之中,那这个location就指定我这个url中,所对应的一个文件夹,那怎么写呢,斜线js斜线可以就给它映射到这儿。

然后我们看一下这个是这么写的哈,那除了这个js里面的资源呢。

我们放行之后,那还有什么呀,还有我们的这个叫做css请求入境中,我们不管前面这块应该什么,前面前面这个斜线应该是从当前项目往后,下面,当前项目下,你想访问css里面什么东西的时候,那我给你意识到什么。

意识到你当前项目下的这个css这个目录里,如果你是当前,像不像这个i m g里面的一些目录啊,你是这个ul,那我给你意识到什么,意识到我当前项目的这个i m g。

这个目录中就可以了,这么写就可以了,那这么写呢,就相当于给这个静态资源放行了,一放行之后呢。

那这个时候这种这种请求,前面其实还有什么,还有这个呃c s s,还有这个gs,还有我们这个呃i m g唉,哎那么一到什么我们这个dispuselect时候,我们在this spa,so let一看哦。

这是静态资源,直接就给你放行了,到你当前项目里面去,对应的目录里面去找静态资源就可以了,那么能好使吗。

我们在这块呢把这个项目重新刷新一下,因为此时并没有增删文件,所以呢我们暂时不需要在这块儿去干,这个事也行,应该也能好使哈,来我们试一试。

这个时候我们再来访问这个index jsp一回车,这个时候我们看一看哈,诶呃这个a a a。c e s s是有的啊,b b b。j s也找到了,但是这个logo。p n g怎么还没找到呢。

这个有可能是我们项目的编译问题,就是maven这块呢可能有点小毛病,就是我们在这块添了一堆静态资源的,有可能一编译的时候呢,这些静态资源并没有成功的编译进,target的目录。

我们到target的目录里面,这个supreme mc,当前这个snap shop里面,我们看一看,这里面你会发现唉就缺少了什么,就缺少了我们这个i m g这个目录,说明他这个图片比较特殊。

这种图片比较特殊,没有成功编译过来,没有成功编译过来,怎么办呢,呃第一种方式我们可以重启idea,重启idea的时候,它会自动检索这个项目,进行一个呃这个出资的一个编译呃。

或者是我们在这块呃重启tom cat,我们试试看看行不行,如果还是不行的话呢,我们可以手动把这个i m g给他,ctrl c复制一下,然后扔到什么,扔到这个spring mvc下面,也可以手动复制过去。

也可以,因为这种文件其实编译的时候,就是把它复制过来啊,并不需要把它进行,像jaa代码一样进行编译,所以能复制过去也行哈,我们重启一下试一试哈,看看它还可不可以。

如果不可以的话呢,还可以怎么做呢,我们还可以这么做,我们可以借助这个maven插件,借助maven插件这个生命周期,这块不是个life circle吗,我们来一个clean把它清掉,清掉完之后呢。

再来一个compile,再来个编译,看一看可怜和compile之后。

能不能把这个给它编译起来,现在呢我们是属于重启tom cat。

重启tom cat时候,tom cat一启动,它也会对我们的项目进行一个编译,但是这个编译,我们似乎在这里面。

并没有找到那个那个文件哈,并不还是还是什么呀,还是没有找到,这还是没有成功将这个logo。png呢给他呃,编译进来,那你会发现这里面还少了一个那c点,cs文件,我们我们浏览器缓存了js文件。

浏览器也给缓存了。

所以这里面有可能会少了两次,但是这个logo的png还是让没有获得到,那怎么办呢,我们做这样一个测试啊,我们把这个呃这个super m,这个这个这个这个用maven先给它可令掉,我先把这个项目停掉吧。

四刀宝把这个两个团不看全都停掉哈,然后再来可怜一下哦,应该啊,他给的目录已经没有了,已经清掉了,清掉完之后呢,我们再来一个compile,用maven再给他compile一下,看看compile之后。

能不能成功的,把这个静态资源给它编译过去啊,这个静态资源编译的时候会有点小毛病,这块呢也是一个坑啊,顺便给大家展示一下这个坑,然后点开点开之后呢,诶这里面这个这个maven这个compile呢。

那还真得干嘛呢,真得我们去嗯,这个呃其中tom cat启动,tom cat可能还会再给我们再进行编译哈,如果还是不行,重启idea应该就好使了,因为你不想重启idea,我如果发现这里面它里面还没有。

我们再把这个复制过去就完事儿了,再试一次哈,不行的话,那我们就用最终手段给它复制过去,唉出来了,出来之后呢,哎看一下i m g已经有了啊,那这回呢我们这个打开呃。

这里面应该能在页面上,应该能看到我们这个图片了哈,好诶也就过来了啊,那么这个就是我们的一个呃,我们的一个静态资源放行的一个操作呢。

就给大家展示完毕了啊,那好在静态资源放行这一块呢,我们会发现有一些地方有点稍稍有点难受,难受在哪里呢,就是这个静态资源目录啊,如果直接放到这个web app下面呢,你会发现有点繁琐,又怎么有点繁琐呢。

这个文件夹将来可能将来只能是cs s,i n g和g吗,有没有可能有一堆其他的一些静态资源呢,文件夹是不是有可能会特别多呢,如果这块文件夹多了,那么我们请求应收入就入境之中。

这一块是不是就可能会造成很多,很多的这个静态资源放行,我可能要写很多条呢,我能不能用一条这个配置,来把所有的静态资源放行呢,也可以,但是呢如果要是用一条这个配置方式,把所有静态资源放行的话呢。

我们的这个项目结构,对于静态资源管理这块呢,呃可能需要做一些特殊处理,你之所以能用一条放行所有的静态资源,那你就要把所有的静态资源,放到同一个目录之中,那怎么放呢,我们可以在这放到这样一个目录之中。

放上一个叫做ttc的一个目录,其实呢我们后面在学这个spring boot的时候呢,spring boot在准备组织静态资源的时候呢,它就会组织这样一个static,这样一个目录叫做静态目录。

然后把这些资源干嘛呢,全给它放到一个目录之中,放到一个目录之中啊,你要知道这个静态资源路径改变了,我们在引入这些静态资源的时候,那这块的路径也得相应改变,要在我们当前项目下。

这个static这个目录里面里面的啊,这个cs里面找这个a a的,cs这块也是在这个当前项目下,s t a t i c static目录下面的里面,再找js目录,再找这个bb点。

js这个i m g也是在当前项目下,static是用static这个目录里面,去找这个i m g目录,再去找这个logo点,png要这么写才可以,那这么写的话,如果放行静态资源的话呢。

也就是说如果你请的资源是static目录里面,或者是你请的路径中带上了这个thetic,那我就认为是静态资源,那么我们在这放行的话,那就简单了,我们就可以用一条来放行了,我们把这个来给他。

ctrl c复制一下,ctrl v,如果请求映射路径中是一个s t a t i c,static static后面有多少层,不但不确定,当前项目后面直接要访问esthetic,静态资源了。

那要把这个location给他,对应应试到哪里呢,对应到我这个static目录里面就可以了,这样的话呢,我们就可以用一个来放行。

所有的静态资源了,这个里面涉及到一个文件夹,一个拖拽了,这个时候呢,我们可能需要重新部署一下项目,或者是重新启动一下,你看这块这个还没有编译呢。

我们在这重新their classes and the resources,我们试一下,看看这里面会不会跟着变哈,如果没有跟着变,怎么变怎么办呢,手动把这个变音之后东西给它删掉。

删掉之后再重新给他弄一下就可以了,应该说这也没变呢是吧,我们先访问一下试一试,可能你访问的时候呢,他可能就会呃这个给我们更新了哈。

现在还没有变是吧,一点这个我们再来访问什么,再来访问那个他试一试诶,你会发现它又不好使了,又不好使,就是说明我们这个编译它没生效,这种静态资源。

编译的时候肯定会有点小毛病,那怎么办呢,再来点一下这个试一试,更新一下,那重新刷新一下我们的项目,刷新完之后就会发现诶,这块就多了一个static目录了,呃那还是这个好使是吧,哎那这个好使的话呢。

我们再来试一试。

如果说他也不好使了,你就把这个tom开关了,重启就好了,这回我们再来试一试,来一回车,诶,还是不好使哦,他请求的路径好像有点问题,是什么问题呢,我们看一看嗯,a对了,这个地方还不能写一个斜线。

如果一写信的话呢,我们当前项目的这个上下文路径就没有了,所以呢这块呢还是找不到这块呢。

是哪儿写错了,是这儿写错了,就是这块别放斜线呃,如果你要是放斜线的话,那你需要在这块,把这个当前项目上下文路径呢给它放的,放的给它放进来,就是我们当前的项目的部署名,要不然的话。

那就去这个就不会给我们自动补充,当前项目项目的上下文路径的,那如果说你想写斜线好使,怎么办呢,你在启动的时候,在这块把这个项目的这个明天给它删掉,删掉之后留个斜线就可以了,就相当于当前项目没名字。

然后呢假期间应该也会好使,但这个大家有兴趣自己试吧,我就不带大家试了啊。

改完之后这些视频呢是不需要我们重新啊,这个刷新项目的,再来一回车,哎这回就好使了,你看这个路径,就是我们当前项目上下文路径,下面之后再找这个static就找到了啊。

那么这个静态资源啊放行的一个处理。

那么我们也就在这块儿给大家。

系列 3:P74:【Spring】SpringMVC_控制请求方式 - 马士兵_马小雨 - BV1zh411H79h

这一小节呢我们讲一下这个关于request map这个注解的那些细节问题。

和一些加了一些控制哈,呃那么这个request mapping呢我们在当前项目中就是加在这个control层次上。

然后用来指定什么,用来指定我们这个呃当前的这个处理单元啊,它的一个映射路径的一个呃这个注解,那么这个request mapping呢,我们现在写的这个时候呢,大家注意哈,前面这块有一个斜线。

那其实这个斜线不加也行,那在这个surprim 4中的这个前面,这个斜线加跟不加,其实并没有什么特别大的一个差别,那么如果说你习惯了的前面加起线,那你就加上就像我们这个at web sol那个注解一样。

如果说你不喜欢加的话,也可以哈,那我们试一试看一看这块,如果说我们不加斜线看看行不行啊,来我们重新部署一下,嗯重新部署完毕之后呢,我们打开浏览器,请求一下我们当前的这个control啊。

来ctrl c复制一下,嗯。

打开浏览器,一会车啊。

ok的也是可以的,也是可以找到了,也就是说这块的斜线加不加都行,那么按照我个人的习惯呢。

我可能还是喜欢加上一点,所以呢我写上就可以了啊,所以给大家看自己的这个习惯就可以了,那么接下来我们就稍稍讲一下这个request mapping这个入解还能够做什么,跟它相关的一些知识点哈。

我们讲第一个叫做request map呢,控制请求方式,我们按住ctrl。一下这个注解,看一看这个注解里面可以填哪些信息哈,这里面有一个默认的一个这个呃pass或者是y6 啊。

他们是一个嗯这个其实这个part跟y轴是一个一个意思呃,我们可不可以可以给这一个这个什么一个这个控制单元提供多个路径,那我们可以写成一个叫做呃pass或者是这个value啊也行,那这是他的一个第一个啊。

第一个路径,那么可不可以再给他多准备几个呢,可以哈,再准备一个逗号,这是一个数组的形式吗,还可以选一个斜线叫做my c o n c o n c u n a a c o n点,a c e t o n。

action,哎这都可以,这都没问题啊,当然一般来说没有特殊情况的话,我们指定一个也就够了,这是他的第一个写法,第二个写法就是我们当前这个request mapping呢,它是可以放到我们这个类上面的。

放到lay上面之后呢,如果我们把这个放在类上面之后呢,那就代表我们要是获取这个处理单元的话呢,那么我们就要在这个我们要是想要想请求这个处理单元,我们就在这个路径之上干嘛呢,先加上这个类上面所定义的路径。

这一点呢我们在上节课其实已经提示过了,在这块就不做过多提示了哈,那这是一个value属性,而我们知道这个value属性如果属性值为y6 ,那我们知道这个y6 是可以省略不写的。

有只给这一个y6 属性赋值,它是可以省略不写的,所以就写成这个样子了,那么这个request mac除了这个value属性以外,还有哪些需要了解呢,还有这个东西叫做叫做method。

这个method能够干嘛呢,这个method能够控制唉我们这个请求的方式,那这是个什么意思呢,我们可以来测试一下哈,呃我们在这块再来一个控制单元吧,在这块我们写成一个呃,public string。

写成一个叫做嗯嗯叫做呃test test a e q u s e request吧,测试请求我们也给它呃,return一个什么,return一个success。

s u c c e s s success,哎,然后呢我们在这儿呢加上这个at request mapping,然后里面加上一个什么,加上一个value,这个value是定义这个应试路径呃。

写成一个斜线,叫做test test r e q e s t request,然后我们在这里面给他说出一句话吧,叫做测试请求,test r e q u e s t,q u e s t啊,简单写了一句哈。

那么我们还可以在这个request map里面通过这个method来控制什么,来控制我们啊,这个允许获取到这个单元它的一个请求方式,那这个method呢它是一个枚举值,我们可以给他多个值。

假设这给他一个,那就来一个叫做request method。

点什么点,这个get意思是什么意思呢,意思就是当前你请求这个控制单元的时候,提交方式必须得是get,那你既想用get又想用pose怎么办呢,它可以附多个值啊,这样写成一个request get多少。

再来一个request request a,这是一个逗号哈,request method的点什么点,这个点这个post p o s t p o s t,那么这样的话呢就是允许什么。

就是允许你当前这个test request可以get形式请求,也可以post的形式请求呃,那么我们来测试一下,那我怎么控制请求是get还是post呢,我们可以通过form表单来指定啊,我们请求的方式嗯。

这个怎么做呢,我们在这个index页面里面来个什么,来个phone表单吧,来个f f o r m four呃,在php里面有一个这个action action呢。

我们给它指定为我们这个当前test request这个action就可以了,呃这块呢建议我们看一看哈,这个当前直接写斜线的话呢,这个在页面上如果写斜线需要加这个当前项目的一个嗯,这个叫做呃上上班路径。

我直接写成相对的就可以了,test request,然后the method这块有个什么method这块有个get和post,那我写成一个get就ok了,然后呢我在这块来一个提交按钮,input嗯。

type type等于type等于呃submit value等于来一个叫做测试七交提交提交,那现在呢我们这个呃这个提交方式呢是get方式提交的,然后请求这个test request。

我们看一看能不能够执行哈,呃在这块呢我们需要重新部署一下这个项目啊。

改代码的话是不需要重启tomcat的,那在这块呢我们要请求的是这个index index jsp可以不用写,然后直接一回车到这块有个提交了。

我们把这个上面的日志呢给它清掉,清掉之后呢,我们在这来测试一下,一点提交你会发现test request是好使的,是ok的,是没问题的,那么如果说我们这块的提交方式是post,它也是可以的,也是可以的。

因为我们这个control这块是允许你提交get和post请求的,但是这块如果说我只要它允许用get方式请求的话,我把这个post给它删掉,那这个时候我们来重新部署一些项目,改代码了,重新部署一些项目。

在这儿呢,呃等这个日志输出完毕之后,还要把它清空。

清空之后呢,我们在这再来刷新一下这个index点啊,这个jsp一提交,你会发现此时呢就是一个405请求方号,不允许了啊,request meat the post not supported。

不支持运筹post请求方式,所以通过这个你就可以控制当前这个处理单元啊。

到底是用get方式请求,还是用post方式请求了,那么这个是我们request mapping这块的第一个呃。

系列 3:P75:【Spring】SpringMVC_控制请求参数和请求头 - 马士兵_马小雨 - BV1zh411H79h

好接下来呢我们讲一个关于这个request map的一个呃,请求参数和请求头的一个控制呃,我们这个request mapping除了通过这个matt的以外控制这个请求方式以外呢,还可以呃。

通过这个pm和这个呃parrom属性和这个params属性和hide属性,来进行一个嗯请求参数的一个控制和请求头的唉一种控制啊,那么这个控制的语法是这样的哈,当我们写了这个参数名之后呢。

如果是叹号某个参数名的话,为什么参数,如果写成py,并且值是这个value的这样一个情况,参数如果是一个pa不等于什么什么外流,但是不能是这个值,还可以通过这种形式来指定多个参数,它的一个呃规则。

那么接下来我们可以给这个测试一下。

这是第一个,他除了能够控制这个请求参数员还能控制请求头呃。

什么叫请留头呢,这个呢我们之前呢也给大家讲过哈,呃我们诶这怎么变成一个再测试一下哈,我们打开f 12,然后呢打开网络在这来刷新一下,看一看哈。

呃我们知道请求呢它分为请求行,请求头和请求体,那请求行呢其实就是这个玩意儿,也就是这个玩意儿啊,然后请求头呢是在这的啊,这是一堆请求头,或者是可同时控制这个头的值必须是什么。

这些我们都可以做这样的一个处理,那么接下来呢我们就对于这个request making控制请求参数和请求头呢。

呃做一个简单的一个处理哈,呃我们在这块呢再来一个要把这个来给它,ctrl c复制一下,这个叫做test request 2吧,嗯这个路径名也叫做test request 2。

这块呢我就不做这个请求方式的一个约束了,嗯然后我们这块输出一个test request 2啊,那么假设我们想呃对这个呃对于这个这个这个单元做这样一个要求。

要是什么要求它的pm加上一个pip a r m嗯,诶诶这个怎么是一个逗号哈,p a r a m的一个注解,然后呢写成一个什么,写成一个叫做名字,为什么名字为叫做user name啊。

意思就是要求参数中必须有这个游戏内容,要是没有的话呢,就会呃这个呃出现一个什么出现一个异常或者请求不允许的情况,那真的是这样吗,我们在这个呃前端这块呢在准备什么,再准备一个form表单吧。

来control c拿过来哎,ctrl v呃中中间来个换行吧,b2 斜线,我们往这个test request 2里面去提交,然后请求方式post还是get无所谓啊,这块我们就用get吧。

因为get这个参数可以带在地址栏上,我们看到这块呢我们可以来一个叫做诶测试,什么测试,测试p a r a m parrams,这个哎这个属性我们看一看行不行哈,呃这个时候呢我们改了代码。

但是没有更改文件位置。

所以呢我们直接在这刷新一下这个就可以了,刷新完之后呢。

我们在这儿访问这个呃,这个index a怎么变成他了哦,还没有更新完毕,再来刷一下,我们一点这个测试params,你会发现它直接出现了1400的一个错误,什么意思呢。

perimeter肯定是use name啊,not meant for actual request perimeters。

呃这儿呢我们在这个上面可以看到这个上面并没有报一个异常日志。

我们看看这里面有没有,这里面也没有,然后这块呢呃这也没有,这也没有的话,没关系哈,我们嗯因为这种四级级的日志呢,可能在这个后台上还真的不好看,不好找,估计记得好像后面还是能看到什么意思。

就是这个请求里面要求必须有这个优势name参数,但是现在目前你这块没有提交优势name。

那怎么办呢,提交一个user name呗,你在这块再来个什么,再来一个input标签,然后呢type等于呃这个text,然后呢给它一个name属性,叫做user name啊,这不就有内参数了吗。

然后这个value值value值的话,你可以在网页上随便输就可以了哈,来回到我们上一个页这一块来一刷新呃,随便写一个r o o t啊,root一点测试pythms。

ok成功了,那么这个就是能够成功的哎,这个控制参数必须要有这个参数,我们还可以可以控制这个参数,什么参数,这个叫做呃不等于什么,不等于root,什么意思呢,就是例如你可以登录我这个系统。

但是呢我控制你当前登录这个系统,这个用户名啊,绝对不能是超级管理员,如果是超级管理员的话,那我就不允许,就是说你这个超级管理员不是一般人能登录的,不是在这块登录的,那怎么办呢,我们可以加上这样一个要求。

就是不等于root,如果说这块要求必须是root管理员,那你可以写成这样一个叫做等于root,那如果要求不等于root的话,不等于root的话,那我加上这样一个是吧,那么还是得重新部署一下项目。

部署完毕之后呢,我们在这块儿回到我们这个呃这个index的jsp这一块来一回车,回车之后,这块呢如果我们写成一个r o o t,然后我们一点测试,你会发现诶竟然成功了。

应该是我这个语法写错了,看一看啊,呃是一个叫做哦应该是有空格。

我们把这个空格给它去掉哈,我们把这个空格去掉试一试啊。

叫做不等于这个root还得重新部署一下啊。

来进行一个测试啊,啊他已经这么提交了,我直接这么刷,其实也行,嗯把这个认知清掉。

哎你看说错了是吧,哎那么这就是控制我们某些属性不能等于什么值。

呃,那么同时呢我还想做一个要求,要求什么要求必须有密码啊,然后但是至于密码是什么,只能我不做确定的明确的要求,那我可以这么写,写什么,写成一个p s s w i d password。

这样的话就是要求你的参数中呢必须带上这个密码这一项。

如果不带上密码是不可以的,那此时我们看一下我们这里面有这个提交密码吗。

并没有,那这个时候你一提交的话,你就算是eu 4内这块,你不写成root,它也会报一个错。

呃等这个刷新完毕哈,啊然后呢在这块儿再来回车一下,写成一个我不写root,写成一个1234哎,然后呢1245也行,一测试你会发现还是不允许,因为缺是一个什么确认一个这个password啊。

那如果说我们在这块呢给它加上一个password的一个参数,叫做p a s s w o r d password,加上这个参数之后。

我们再来这个不用重新部署也行,因为这是一个h j s p g s p应该是不需要嗯这个更新的啊,多了一个这块是一个密码,1234账号这块再来一个一二就随便写,不写都行啊,来一点测试。

你会发现这个时候就是ok的。

那么这个就是关于什么呢,这个就是关于我们的一个请求参数的一个这个控制就搞定了,搞定之后呢,我们再来测试一下它能不能够控制请求头也是可以的,也是可以的,这块再来一个test request 3。

这块也来一个test request 3,然后呢假设我想对请求的请求头进行控制的话呢,我们可以通过这个就不用这个pyms了,我这块就不加这个参数控制了。

可以通过这个headers h e headers来进行一个控制,语法呢跟我们这个parroms这个语法呢基本上是一样的,呃假设我想控制必须有什么头,头,必须有什么值,那我们就参照这个语法写就可以了。

我们在这块呢作为一个了解做一个测试就可以了哈。

呃我们看一看这个请求里面,这个请求里面呢,其中有这样的很多很多的请求头。

那么你可以把这个请求头和请求值呢拿过去就可以了,例如host这一块呃,假设不需必须不能是本地的一个访问,那你可以把这个后侧裙头放上去,呃,我们这块可以拿拿这个吧,这个相对来说比较短一点是吧。

我们拿这个accept encoding叫做接受的一个呃这个压缩方式。

这个头呢可以试一下,我现在要求请求这个组件的时候呢,它的这个什么呢,它的这个叫做accept encoding的这个属性的值,encoding这个属性的值,诶,嘿。

它必须等于这个z i p逗号叫做d e f l e t啊,必须等于这两个值,如果说你等于的不是这个值就不行。

呃,那么我们试一下,看看这样行不行哈,我们呃这个时候应该应该应该在这块需要重新,因为改的是java代码,需要在这块重新刷新一下,部署一下我们这个项目了啊,deploy on。

刷新完毕之后呢,呃我们回到什么呢,回到我们这块来,然后一点测试,ok成功了,因为此时呢我们提交这个请求,它的这个acception coding这个头就是这个值。

那假设呢我在后端要求说这个in coding这个值呢只能是这个头啊,这个值只能是他不带后面这个了。

那如果说我们再次请求,还是用这个图去请求的话,那一定会出现一个啊这个请求不允许的情况。

这个java代码又改了,我们在这块再刷新一下。

哎说完之后呢,回到这儿来。

回到这来之后呢,我们再来呃进行一个测试一走,你会发现诶怎么又过来了。

应该是这个项目没有成功刷新是吗。

哦这是太自私了哦,写错了,这个form表单应该再来一个,我让他去请求三去,应该请求这个三去啊,来我们试一试哈,这个请求方式是get还是post。

跟这个没关系哈,这个js p改了之后,这块是不需要重新部署项目的。

最后我们来测试一下,来一点走起来。

就是它并不是什么呢,你看你这个请求呃,这个请求提交的这个请求头,它是一个accept coding。

为长这个值,而现在呢我们要求这个accept in coding呢,对于这个ctrler呢,这个头呢必须是这个值多那个逗号和那个什么d e f不行,那是不允许的,那我再把这个加回来呢,你把这个加回来呢。

加回来之后呢,我们看一看对应这个请求头的一个呃。

这个处理单元它能不能够访问得到哈,呃在这块呢再来啊。

再来直接刷新一下诶,你看啊直接就success就访问到了。

系列 3:P76:【Spring】SpringMVC_@PathVariable注解 - 马士兵_马小雨 - BV1zh411H79h

呃接下来呢我们给大家介绍一下这个pass variable这样的一个注解,和一个rest风格的一个支持,呃那我们先说一下这个pass的呃variable这个注解它有什么作用哈。

嗯那么我们正常在请求我们当前项目里面的资源呢,这个u i l或者ui是这么写的,前面呢我就略过了哈,我写这个ui它可能是我们当前这个呃context path,就是我们当前这个上下文路径。

然后后面跟上我具体的作为名,例如它是呃,假设是我们这个嗯叫做嗯a a a诶,点do哎,或者是我们在请求某些资源的时候,来ctrl c拿过来是吧,可能是某个aaa啊。

这个点jsp啊啊或者是a a a a a。html啦,或者是访问我项目里边的这个cs啦,嗯或者是这个js啦等等一系列资源呃,那么这块写成一个css,这块写成一个gs,那么我们如果说在请求的路径中有。

如果要是带上参数的话,该怎么写得这么写,那怎么写啊,那么请求我们这个呃这个control层,然后带上一个参数,用问号作为分隔符写啊,带上应该叫做i d等于一个十,然后呢user,然后再来一个and符呃。

user name啊,等于一个假设叫做r o o t啊,那么这个是带参数的这样的一个写法呃,那么我们说这种写法呢,它是不是叫做restful风格支持的这个呃支持的这样的一个写法呢。

并不是呃其实呢我们如果要是在页面上通过这种写法呢,大致上都可以推断出来就是我们访问的资源是什么,而且甚至呢有的时候带上参数的这些东西其实都是暴露出来的,呃我们可以干嘛呢,我们这种风格其实不是特别的好。

呃相信大家我们在互联网上在访问某些资源的时候呢,并不是所有资源都是什么什么点js p,也不是像是戴上这种点拓展名的这种资源的,可以给大家举个例子哈,呃我们找京东吧,京东上面有很多这种东西。

京东那看吧,嗯随便找一件产品,摩托车来吧。

摩托车像这种东西,我们看一下,你看这个就是符合我们通常那种啊叫提交方式的,一个一个呃一个u i l呃。

这个好像符合restful风格知识还不是特别好找,我们搜一下手机。

那手机呃点一下这个吧。

嗯这个也是呃非restful风格支持的。

哎这还真不是特别好弄的,这种呢就得挨个去世,我找一找哈,这种啊这种啊这种也是点什么。

是html这块真的得发现一下试一试。

我们公司官网试一下呃,在我们公司官网这块呢有这样一个界面。

就是go ob的一个界面,go ob的一个界面,你会发现这块呢我并没有写什么go b。html啊。

或者什么点jsp啊,或者什么东西,我只写了一个勾b。

然后一回车之后呃,你会发现他就做了一个页面跳转,那像这种风格呢,我们说它就是一个呃restful风格的一个支持,那也就是说我们的ur l这一块呢其实可以怎么写呢。

我们假设要是想提交请求某个资源,或者带上某个参数的话呢,我们可以写成这个样子,r e s t r e s t restful啊,风格支持的这个ul其实可以这么写来ctrl c ctrl拿过来。

假设你还是请求这个a点度,当然这个点do是我们自己定义的哈,我们可以不起来,我们直接写成a也行,那后面参数可以怎么办呢,可以这么带来一个斜线,然后来一个十斜线,然后再来一个r o o t这么写也可以。

如果是访问某些页面资源的话,那假设我想请求我这个呃呃请求某个页面,请求某个页面,我直接可以把这个页面名唉放在这一块儿啊,就是不带这个什么什么点拓展名了,这么写也可以。

那么这种就是我们所说的restful风格知识,那你可能会说这块如果说我要不带什么点的话,不带什么点html的话。

那能被识别吗,可以被识别,我们可以在这个control中啊找一个ctrl,然后呢在这里面获取什么,获取ui中所对应的一些路径,然后拿回来之后呢,以这种方式啊,这个请求转发到某个位置也是可以的啊。

那好那么接下来呢我们就来测试一下这个什么呢。

就是这种写法哎我们用这种写法去传递数据的时候啊,或者是呃在我们这个处理单元上,后台ctrl上处理单元上如何获取我们请求的路径中的上面这些数据,当然这只是传递数据的一种方式哈。

那你说如果要是用post的方式的话,那可能就是参数就不往这儿放了啊,或者是呃就是放到呃呃或者是用其他方式,我参数包装放也可以,那能不能够提交数据的,也是能够提交数据的话,我们先测试一下。

看看当我们的u i l写成这种格式的时候,它怎么对应到我们后面的这个control层,动到某个数据单元哈,然后呢怎么解析出这个路径中的这些东西拿出来当成数据来使用啊。

那这个该怎么玩儿的哈,我们在这再来一个control吧,假设这个叫做my control 2吧,叫my control 2,也不叫my control 2了,叫什么呀。

叫做呃p a r e p a t h park cler,唉我们拿这个看出来演示吧,诶诶怎么跑到外面来了,呃,在这个part control里面呢。

我们还是要给它加上一个at controler的一个呃这个注解,然后呢我们在这块添加一个处理单元,来一个叫做public public string。

然后呢来一个叫做呃test test p a t h path,variable vr a嗯,v r i a b l e variable,a b l e variable的一个这个注解的一个方法。

那么在这块呢直接return什么,还return这个这个success s u c c e s s,我们还是往这个success这个页面上跳呃,加上一个什么,加上一个at request map。

加上一个add request making之后啊,那么我们如何在页面上请求这样的资源的时候。

请求这样的写法的时候,能够对应到我们这个啊这个request map呢我们可以这么写哈。

首先第一个我们可以写成一个叫做呃test,叫做test一啊,test一或者是直接写也行,test test past variable,然后呢我们直接在后面再写什么呢,因为我们在这个写完路径之后。

我们可能在我们浏览器上,我们可能在写路径的时候呢,要在这个路径后面再加上一个十,再加上一个username,那我们后面这块应该怎么写呢,对吧,就会出现这样一个问题了,我们在这希望获取个id。

然后在这希望获取它的一个叫做user name,嗯,或许他username,那如果说我们直接这么写的话呢。

跟这个是不匹配的,为什么跟这个是不匹配的,为什么不匹配的。

嗯,还拿过来哈,如果我们在这块这个定义这个路径是这么写的话呢,要求你在这个pass viable后面不能写这个十,必须得写成i d这个值,然后呢在这个use sername这块必须写成什么。

必须写成use sername啊,不能写成root,这个东西并不会把这个东西当成参数给你解析,那如果想当成参数给你解析的话,我们该怎么办呢,在这块用一对大括号给你扣上啊,你的大括号把它俩给扣上,诶。

那扩上之后呢,那么我们这个请求运输路径只要是以这个test pass variable开始的,然后后面只要跟上两段的话呢,诶就会跟他匹配上,匹配上之后呢。

我们可以在这个处理单元里面获取我们在请求映射路径中,这块所放的值和这块所放的值,那真的可以吗,我们可以试一下哈,我们先试一试,看看能不能请求到这个啊,ctrl之中。

然后我们在这输出一句什么输出一句这个吧,test pass verbal 1,哎,我们试一试看看行不行哈,呃那么这个该怎么准备呢,我们可以在index里面还用form表达了吗,这个可以不用放表达。

那我们可以直接干嘛呢,可以直接在请求应试路径这块直接后面拼就可以了啊,就没有这个没有这个用form表的那个必要了。

我们先试试看看这种方式行不行哈,呃我们在这儿呢需要啊,因为增加增加文件了,我们在这刷新一下项目,看看行不行哈,那么我们在这里请求这个叫做test variable,这样的一个什么这样的一个这个呃累啊。

这样的一个这个ctrl,然后一回车你会发现找不到找不到,为什么找到,因为他后面还要求你有两段呢是吧,哎再写成一个什么,再写成一个十,再写成一个user name,写成一个root,那看看能不能找得到哈。

诶这回就找得到了,成功的找到了我们这个呃,找到了我们这个test variable variable啊,这样的一个呃这个处理单元。

但是呢你可能是我们之前说过,就是我在这里面是能够成功地将这个十和root解析一下,解析完之后呢,在我们这个处理单元里面是可以获取我们在路径上在这块填的值和,在这块填的值,那怎么解析呢。

我们可以在这个括号里面添加两个参数,一个是string的一个id,然后再来一个逗号,再来一个string的一个user name,那么用这两个参数来接收什么呀,来接收这块这个值啊,和这块这个值。

那这两个参数往这一放,能够成功地接收到这块的两个值吗,我们来可以试一试啊,我们输出一下啊,输下这个id冒号,加上这个id诶,然后再来一个呃这个这个username,username诶。

加上这个诶username,user,看一看能不能够成功的将这个id映射到他身上,将这个username映射到他身上,我们可以测试一下哈,哦上面等他日日打印完毕,日打印完毕的话呢。

我们说明这个重新部署已经ok了,部署ok之后呢,我们在这再来来刷一下,说完之后呢能够成功访问到,但是你会发现这个id和use name是一个now,也就是说如果我们这么写的话呢。

并没有将这块这个id成功的映射给这个变量,也没有将它这这一段的这个ul,那内容呢映射给这个变量,那怎么才能映射上去呢,我们需要在这块加上这样一个注解,叫做at pass啊。

pa t h variable的一个注解,然后在这个注解里面指定什么呀,指定它这个y轴属性等于什么,等于这个叫做i d,我们现在呢这个注解是加在谁身上呢,是加在这个参数身上了。

pass variable的意思就是这个pass就是路径的意思,variable就是变量的意思,就说白了就是把路径里边的某个值拿出来放到某个变量上,就这个意思或者放到参数上。

然后这个value值是可以省略,不写的也不行,那么这个意思就是我们要把这个路径里面id这一部分解析出来,放那a放到这个string id上去,那我要想把这个eos name解析出来,放这个上去。

可不可以也可以再来一个at p a t h pass verable,然后呢指定这个名字为什么指定为这个username,注意哈注意这个名字啊,要跟我们路径里面的这一段匹配啊。

这个名字自然而然也要跟这一段匹配,有意思,就是把我们路径里面这两段的值拿出来,分别复制给这个变量和这个变量,而我们下面此时这个名字和他非得一致吗,他俩是可以不一致的啊。

然后这个名字参数名一定是跟他一致吗,他俩也可以是不一致的,那么我们先试试加上这个at pass river之后啊,能不能够从路径中直接解析出这个值,诶怎么搞,搞到笔记这一块了,打开我们这个浏览器。

然后在一块再来来一刷新,我们看看后台诶,这个十和root就已经拿到了啊,那么这就是在我们的ul上的这个呃这个体现的htp协议上呃,这个ul上体现的一个呃这个restful风格的一个支持。

通过这种方式可以传递参数了,那你说假设我想控制页面跳转,那你可以直接把什么呀,你直接可以在后面呃,假设我想跳的那个页面的时候,我这块只写什么。

只写这个s u c c s u c c e s s这个size可不可以,可以,你把这个success在后台这块接收一下,接收完之后呢,再把这个值再把这个变量值直接作为返回结果return。

那不就是你对应的一个路径了吗,那这样的话你就会感觉哦在这块只要传一个名字,不需要打这个html jsp就可以直接进一个页面跳转也是可以完成的,当然这个呢是是后话了哈,但是通过这样一段代码的。

我们至少还测试出来了,我们是可以取出什么呢,通过这种restful风格知识的url是可以取出呃,那么我们ul上的一些呃某一段的一些数据的,这是ok的,这是没问题的,嗯,再加一点小疑问吧。

一个什么小疑问呢,这块我如果写成一个integer,可不可以,i n t e这一行integer可不可以,这是个什么意思呢,就是正常ul里面的东西啊,就算这块是什么,这块就是一个数字。

也会当成一个字符串来进行处理,那我这块写成一个integer类型,那我们这个pass variable会不会给我们做一个转换呢,那我们可以测试一下,看一看它能不能够转换,看一看它这个强大之处。

好重新部署完毕,然后我们在这儿再来啊,再来来刷新一下,看一看后台,你看它仍然是可以解析出来的,也就是说它无形之中呢也是给我们可以,可以给我们做一些数据类型的一个转换的。

那么这个爱的possible还是挺强大的一个呃这样的一个注解的,那么在这块呢给大家介绍一下,我们这个ul中这种restful风格的一个支持。

呃那么接下来呢我们可能就要说一下这个restful风格支持,这个rest rest到底是一个什么东西啊,什么叫做restful风格支持,然后在这块再讲一下我们这个http协议中啊。

这个请求的四种什么四种这个请求方式啊。

然后这四个状态分别是什么意思哈。

系列 3:P77:【Spring】SpringMVC_RESTFUL风格 - 马士兵_马小雨 - BV1zh411H79h

上一节呢我们给大家分析一下这个passworable注解它的一个作用,以及rest restful风格的一个这个支持,那么我们说普通的ui l格式呢就是更重要的路径,然后后面什么点都点js p等等。

可能还会带上西山西,带上一些参数等等,那么如果是restful风格制式的风格的呃,这个ul呢它是这种格式的,那么我们说在这块呢嗯简单介绍一下这个restful风格是个什么东西哈。

然后呢通过这个restful风格,我们再来给大家演示一下,我们这个呃htp协议它的这个四个啊,这四种提交的方式,也就是我们所说的这四种状态啊,rest即表示嗯即表述性状态传递。

那么呃是一个叫做law什么什么fielding的一个格law for field格式呢,在这个2000年他的这个博士论文上体现出来的软件架构风格,也就是说rest rest它是一种软件架构风格。

呃那么它并不是一个这个呃强制的这个这个这个规范,那么呃它的基本含义叫做表述性状态转移,是一组呃架构约束条件和原则,满足这些约束和条件原则的应用程序呢就是restav,那么呃值得注意的是呢。

就是restful,它arrest不是一种标准,他只是提出了一些约束条件和原则而已,而rise呢通常呃通常基于使用htp,目前也是在http上呢,呃这个支持他的这个rest的一个风格。

那就说它其实就是一个呃这个风格而已啊,一个一组约束和条件而已,它并不是一个技术标准,那么他这种表述性状态转移到底是一个什么含义呢,可能我们第一次看这个含义的时候,发现它并不是一个什么。

并不是一个可以直接让人理解的一种语言或者一种描述,就是说白了不像人话呃,那么什么叫做状态转移,我们给大家举个例子哈,在http协议上,在http协议上是可以通过这种表述性状态变化来表示不同含义的呃。

在http协议中呢有四个表示操作方式的都是个动词,就分别叫做get和post,这两个其实我们很熟悉,但是还有还有两个叫做put和delete,他们对应的是四种基本操作,get是用来一般用来表示获取资源。

pose,用来表示新建资源或者是传递资源,put的用来表示更新资源,这个delete用来表示删除资源,那么这四个动词它有什么实际的应实际的这个应用和含义吗,还是有的,简单的说就是我们在访问资源的时候呢。

可以通过这四个状态来表示对于资源的这个不同操作,那么这四个状态呢,其实呢就是呃对应的就是我们http协议中的四种请求方式,其中有两种请求方式我们已经见过了,一个是get请求,一个是post请求。

举个例子哈,假设我们请求的这个u r l同样是ctrl 1 ctrl后面带上一个一,那么如果说这个在http中我们用get来请求的话,那么其实啊这个含义可以理解为是得到i d v一的资源。

我们可以这么理解哈,如果说我们是用这个delete方式来进行请求的话呢,那么可能就是表示出来这个删除i d v一的资源,如果用put的方式请求的,就是在更新i d v一的资源,如果是用post请求的。

就是增加i d v的资源,那我们发现我们请求的url呢它其实是一致的啊,是一样的,但是随着我们这个请求的状态发生了变化啊,那么我们这个ul呢它所对应的资源也会有一个转移。

其实呢这就是可以简单的理解说一下什么叫做表属性状态转移呃。

简如果说详细的去分析这个rest风格啊,rest for风格的话呢,那我们可能还要把这个low什么什么fielding这个博士,这个博士的论文呢还要再读一下,那可能就是呃比较花时间。

那么我们通过这个呃这个这个呃这个四个get delete和put put,还有post,那么这四种请求方式呃,在http协议上呢。

呃这样的一个这个实现给大家展现出来这个表现,这个叫做表述性状态转移,它是一种什么感觉,大家做一个了解就可以了哈,那么其实呢就是我们在请求同一个control的时候呢,用四种四种请求方式。

然后呢呃对应分别四个不同的ctrl也就可以了,就达到我们的目的了,所以呢接下来我们就要干这个事啊,把这个把这个事情给大家说一下,就是呃通过在在这个访问什么的访问,那同一个这个url的时候时候啊。

那么通过什么呢,通过这个呃不同的呃不同的请求方式,哎然后呢对应什么对应对应到这个不同的啊,这个ctrl还处理单元嗯,处理单元,那么我们先拿这个最简单的这个get和post来进行一个测试哈。

呃我们打开我们的项目,在这块呢还在这个pass control里面,我们继续写嗯,在这呢我们再写一个这个叫做public string cha stream啊,这个叫什么叫做test get吧。

这样的一个代码,那么我们要给他一个请求的一个应试路径,at request mapping,然后呢里面写上一个诶,我我不在这里写了,我换一个吧,这块儿我可以来一个叫做the test test。

e s t restful风格支持的一个这个controller,然后来一个at controller,还是定义这样一个方法,public string呃,然后再来一个叫做get test,get。

test get,我们给它一个请求的一个应试路径,at呃,require a at request mapping,然后呢我们可以写成一个叫做呃叫做诶。

我看看我这个笔记上的那个路径名叫什么呃,我这个笔记上的路径名叫做test rest。

那好我也来个test rest,test e s t d,然后来个斜线,后面这块呢我们放一个id,这个id呢我希望解析出来放到我们这个呃处理单元中,作为一个参数能够获得。

那我们可以来一个string的一个id,那么前面呢要是想把这个a d呢给它放到这个变量式上去呢,我们需要给它来一个叫做at p a t pass verbal。

然后呢指定我们pass路径里面的这个这个i d哎这个解析出来,解析出来之后呢,放到这个哎这个属性上去,然后呢我们在这输出一下嗯,可以在这输出一下嗯。

那么嗯输出为什么输出为这个叫做呃test get get get,然后这个id值嗯想获得就获得,不像获得也行,然后呢加上这个i d也是可以的。

然后呢我们在这块return一个s u c c e s s success,s u c c e s s success,我们检查一下,在我这个mc中呢,我好像已经配置了这个视图解析器。

它会自动补充前缀和后缀,它会给我们,那我这块如果是return这个呃success的话,他应该会跳到我们这个web i n f view里面这个success。j s b界面。

这个咱们之前操作过哈,右击close others,嗯,然后呢我们就写一段代码来请求什么,来请求我们这个呃这个test restful里面这个处理单元。

然后呢我们先以get方式请求,然后再以post方式请求,看一看啊,这个能不能有这个对应的一个差别哈。

嗯那么我们在这个index。jsp里面,这已经有几个form表达了,那我们用它呢,不用它了,再来一个叫做叫做test page吧,一个点j s p,我们在这块呢再准备一个放表单。

然后form表单给他准备一个action嗯,为这个叫做,唉请求它吧,但是这个就前面不要加斜线了,因为加期限就要加项目的这个上下文test right。

然后里面放一个十me为get方式请求get方式请求啊,来一个呃input type button y67 70可写,可不写了,一个叫做呃叫做get嗯,get方式提交请求哈,这个就不用看了,回到这儿来。

那我怎么知道这个东西对应的是get呢,我们通过它的一个叫做matt来指定来指定什么,来指定这个request method为get方式,那这样的话呢就说明你当前请求呃这个嗯这个注册的这个组呃。

这个这个control的一个单元的话,必须要通过get方式来请求,那我们启动我们的项目来测试一下,看一看行不行哈。

好我的项目已经启动了,但是它默认打开的是index jsp,我们打开这个test page,点js p回车进来,这块有一个get的请求,然后我们这块一点看一看,诶,后台这块好像并没有请不到是吗。

什么原因,哦是supermit写错了嗯,在这块重新再来一个刷新,然后一点这个get,你会发现成功的请到了这个呃test get啊十啊,这样的这个test get这个数据单元没问题是吧。

那么如果这块我们要是来一个呃,如果是我们来一个提交post请求的一个方面表达,把这个改成改成改成什么,改成post,改成pos之后呢,这块呢是个名给它改成post吧,这个里面改一下。

然后这块再加上一个换行符,换个服啊,好那我们试一试看看,如果说我们用post请求在请求这个资源的时候能不能够匹配到哈,这个应该就怎么说呢,应该就会出现一个这个异常了啊。

然后呢我们再来一点post请求方式不允许了,我们已经在这个control这个处理单元上已经加了这样一个要求,它必须是get方式请求,那如果说再来一个post方式请求的话,那我们来试一试啊。

来ctrl c复制一下,往这一站呃,我们这个方法名的人不叫test get了,就test post,然后呢这个输出这块也给它改成test post,但是呢这个请求的方式这块呢要给它干什么呀。

改成叫做post就可以了,但是你会发现哈,这里面请求的这个u i l并没有变化,也就是说同样一个ui,同样一个ul啊,那么这个i d值它虽然是可以变化的。

但是如果说是相同的u l可以根据这个请求方式的不同,给它映射到不同的什么不同的这个处理单元上,那么表现出来就是呃这个ui l中如果带上了这个表述性的状态。

那么这个请字处理单元会随着表述性的状态转移而变化,那么我们试一试,看一看这个post请求能不能对应到它哈,呃然后呢在这块儿回到上面也改代码了,改代码我们需要在这块重新部署一下项目,嗯重新部署完毕之后呢。

我们再来一点这个post,你会发现后面指的是就跳到了test post这一块,回来get就跳到了test get这一块,那我们发现请自这个u r l它都是一致的啊。

你看这个请求的url还是他这个请求ul唉也是他啊。

都是一样的,那么这就是随着表述性状态转移啊。

那么这样的一个达到一个效果,那么在这个http中呢,它不仅仅可以提交这个post请求和get的请求,还可以提交另外两个请求,这两个请求是什么呢。

这两个请求一个叫做put请求和一个叫做呃这个delete请求,那么接下来呢我们就来测试一下这个put请求和这个和这个delay请求。

该怎么提交哈,呃在我们正常的这个页面中呢,如果说我们的form表单要是想提交的话呢,我们想提交一个put的请求的话呢,在这个matt里面呢,它是只有get和这个post的。

也就是说我们在写法上这块只有这个get和post,但如果说我们要是想请提交一个put请求该怎么办呢,我们需要在这块呢带上一个参数,我们需要带上一个特殊的参数,请求中携带一个什么呢。

携带携带一个特殊的这个参数,这个参数的名字叫什么呢,这个参数叫做下划线m e t h d max,然后呢用这个用该参数,用该参数,用该参数来表述什么的。

来表述这个呃这个put和什么hot和这个delete请求,那样子的请求,那怎么表述呢,在这块儿我们可以来一个什么,来一个这个呃,再来一个input吧,嗯input一个input,输入标签。

然后呢type呢我们可以给他来个什么type,给他来一个叫做hien,什么意思,就是隐藏,但是隐藏的话呢仍然会将这个呃这个这个输入标签的数据进行提交,然后它的name属性值呢必须要什么。

必须叫这个下划线matt,嗯,必须叫它,然后呢它的value值是什么呢,它的value值就是我们要请求的方式啊,例如我这块呢想用一个put方式请求,就来一个p u t就可以了,那么这个时候要注意哈。

上面这个form表单里面这个method仍然用post,仍然用post,然后呢在post里面携带一个参数,叫做下划线matter name,如果这个值对应的是put,那么此时就代表他是一个put请求了。

那如果是我想提交一个什么呢,如果是我想提交一个这个啊,这是一个铺的请求哈,我想提交一个delay的请求,怎么办呢,跟这个类似,诶这个怎么跑到后面去了啊,跟这个类似。

我们只要把这个matt的锁定的只能改成什么,改成d e l e delete就可以了,然后这块也改成一个d e l e t delete,那么它就是一个delete请求了。

呃那么呃那后台这块能区分出来吗,目前来看应该还是区分不了的话,我们可以试一试,我们把这个来给它ctrl c复制一下,我先找一个对,先写一个对应put的请求的,那这块首先它得改成p u t。

然后呢这块可以来一个test p u t,然后呢名字也叫做test p u t,那么除了一个put以外呢,还有什么呢,还有再来一个ctrl c拿过来,还有一个是delete。

d e l e t delete,然后这一块呢再来一个d e l e t delete,那这块一定是一个d e l e t t delete,那么接下来我们测试一下。

看看当我们用这个put请求和delete请求能不能请求到这两个处理单元哈。

他这个输出是怎么样的,我们来测试一下嗯,重新部署一下,好部署完毕之后呢,我们看一看这个delete它能够对应到对应到哪个control上去哈,一会你会发现它走的还是post,然后呢再来那再再走到上面。

再走这个put这一块,那你会发现它走的也是post,也就是说当我们上面这两种请求方式哈,呃用这种方式是取决提交post请求和delete请求的时候呢,你会发现它并没有给我们识别到什么。

识别到后台的这个这两个处理单元身上,那可能说这个是因为form表单提交不了嘛,也不是因为这里面呢我们需要配置一个什么,需要配置一个请求的一个过滤器。

配置哪个过滤器呢,就是h form表单本身是没有办法提交这个delete请求和post请求,put请求的,我们需要一个过滤器,然后通过一个过滤器呢来把这个呃。

把这个post请求转化成delete或者是post请求啊,就是通过这个配置叫做hien http method filter,它的作用就是什么。

就是一个叫做将什么将这个post请求可以转换为put和delete请求,那怎么配置呢,原模原样的把这个给他ctrl c复制一下就可以了。

在我们这个web。xml之中嗯,在这,点点错了。

web的插标之中,我们配置一个啊这个过滤器就是它那叫做hen http method failter,叫做隐藏的http方式的一个过滤器。

它使用的是我们这个mvc里面的一个叫做hien http method filter,然后这个filter呢他要过滤所有的请求,那么他在过滤所有的请求之后呢,它就会它的内部的一个内部的一个功能。

就是将什么就是将这个呃将post请求给转化一下,那它是怎么转化的呢,我们可以按ctrl。一下这个类名,然后跳到它的源代码上,可以简单阅读一下哈。

呃这里面有一个叫做do filter internal的一个方法,就是做内部请求的方法,那么他做了这个事先获得这个request对象,然后呢从这个request对象中去获取这个method。

就是请求方式对,如果说他是一个什么,如果说它是一个post请求了。

就要做一些特殊处理,如果说他不是pos,如果说他不是post请求。

就直接干嘛,直接是一个像这个呃这个叫什么,这个叫做请求的一个过滤器呢,传递给下一个过滤器就放行就完事儿了啊,那么如果是post请求,他会怎么做呢,它会获取一个参数,它会获取请求中的一个特殊特殊参数。

那这个参数的名字叫做this mess parrom,然后这个this。mamac parra是个什么玩意儿,它就是我们这个下划线max的,那也就是说他干了一个什么事呢,他在这解析了一下。

先获取我们请求参数中有没有这个下划线m e t h o d这个参数,嗯,然后呢嗯有之后就是下面就开始做一堆逻辑判断了,这一堆逻辑判断可能大家看的不是很顺畅。

我直接在这给大家解释一下,这是什么意思啊,这个图在这里画好了。

请求的这个处理逻辑是这样的哈,他第一步先判断是不是post请求,而如果是post请求的话呢,那是post请求的话呢,呃他就读取一下,你当前这个请求中有没有下划线max这个参数如果没有,是一个now的话。

如果这个参数它是一个闹市的话,他就给我们应试到什么,硬到这个max为post请求本身上去了,哎然后他如果读取这个参数,它带上这个matter了啊,然后这个value值被delete的时候。

发现这个值发现这个下划线met值是delete的时候,它就会什么呀,它就会将我们这个请求呢给它映射到什么,映射到我们这个请求方式为delete这个这个处理单元身上去。

如果发现这个下划线math值是post的,那自然而然就往上面就往这个方请求方法上为为要求是哎,这个这如果这个下划线matter是一个put,那么它跟这个值就一样了,哎这块这个这个这个这个写错了。

我应该换一下,这块应该是一个put,一会把这个图更新一下,如果发现这个只是一个put,就会把这个什么,把这个把这个请求给我们映射到这个request matter这个put上去。

所以说这个呃http had method这个filter,它就干了这样一个事,那这样的话呢就可以区分我们当前项目里面这个delete请求和不得请求了。

那么我们可以试一下哈,但是在试之前呢,这个我之前试的时候呢,它有一个小小的一个问题啊,我们做这个事就是给大家解释一下这样一个小问题啊,就是看这哈,呃目前呢我们这个success呢是当成什么。

是当成这个嗯,是当成这个一个页面的一个路径来返回的,那假设我想单纯的把这个这个字符串当成一串信息,返回给我们的浏览器,我们该怎么办呢,我们可以把这个control给它改成什么。

给它改成改成叫做rest control,改成rise control之后啊,那么这个ctrl下面所有的这些处理单元所返回的这些字符串啊,这些字符串都会被当成文字,直接想给浏览器,而不是不是什么。

不是这个当成我们这个呃请求的这个页面跳转的页面路径了,为什么要改它呢,因为就是这个delete请求和这个put的请求在页面跳转的时候呢,可能会出现一些异常,但如果说不不不,如果说不做页面跳转。

直接返回信息的话,那就没有这种异常啊,那我们试一试哈,来呃看一看能不能够测出来,我们先把这个结果测出来再说哈,我们回到回到这一页再进行一个刷新,刷新完之后我们测试一下get方式仍然可以过来。

但是你看这个时候我们俩就直接收到这个文字展现出来的是吧,然后一点post它也是success,下面也是一个post,ok也没问题,然后呢我们来测试一下这个put,你会发现它走的就是这个put了啊。

他终于可以识别这个获得请求了,我们再测试一下这个delete一点这个delete诶,他也过来了啊,那么整个的这个呃ul中通过四种不同的请求方式啊,这个表述性状态转移之后。

对应的这个请求资源也是一个转移的那种效果呢,我们就把它展示出来了,那这个呢作为一个呃了解就可以啊,那么大家有兴趣的可以测试一下,如果说没有兴趣的话呢,大家简单的能够学会使用什么。

能够学会使用我们这个在请求路径中这么写,来支持rise和风格就也就可以了,当然这种方式呢它只是一种ui路径的一个restful风格的一个支持,呃,在时间研发中,我们会不会用这种方式来提交大量数据呢。

其实不是很推荐,为什么不是很推荐呢,呃如果你想要它提交大量数据的话,那你这个url呢会写的很长,而且呢它仍然是有什么,仍然是有这个暴露数据的一个风险在里面的。

那么我们只是用它来简化我们的u i l还是ok的,还是没问题的哈。

那好那么这个restful风格知识这块呢。

系列 3:P78:【Spring】SpringMVC_参数注入引入 - 马士兵_马小雨 - BV1zh411H79h

嗯接下来我们讲这个四bm mc中的非常非常重要的一个知识,叫做获取请求参数,或者叫做呃这个参数输入都是一个意思哈,呃是一个什么含义呢,就是呃我们要获取请求的数据了,参数了,就这个东西。

那spring mvc呢已经对我们这个请求方请获取这个参数的方式,进行了一个非常好的一个封装,可以极大地简化我们获取参数的方式,那么接下来呢我们给大家演示一下哈,先给大家简单演示一下这种解耦合方式。

参数注入,以及后面呢我们主要使用的这种sol和解耦合方式的这种啊,这个参数输入啊,那么这个不光是推荐,而这个是什么呀,这个是必须熟练的,后面的我们主要就是讲这个东西,但是我们要先理解一下这个东西啊。

这是什么情况呃,那么我们在我们这个项目里面呢,我们准备什么呢,准备随便准备一个control吧,用来接收参数,那我们这块可以来一个叫做呃叫做test test,dt test b data,ctrl。

啊test det了哈,然后在这里面呢我们用来接收参数,先来个啊这种什么这种紧耦合方式,就是呕度比较高的方式啊,紧耦合方式哎这个参数主解耦合方式的参数注入呢。

其实啊跟我们这个之前呢在使用ctrl的时候呢是一样的啊,那么什么意思呢,就是呃就是使用什么使用使用这种传统的传统这个http soviet,request对象,那获取,然后呢另一种方式呢就是什么。

另一种方式呃,就是我们的一个叫做松耦合方式,那松或者是解耦合,解开解耦合方式参数,这比较熟悉的参数注入,同意一下a啊,那好那么使用解耦合方式参数数的话呢,它是什么意思,就是不使用什么呢。

不使用这个http server light request对象来获取参数了啊,就开始参数了,哎通过什么,通过这个我们的一些呃这个spring mvc框架中的这个呃处理器适配器啦,呃处理器适配器。

然后呢框架中的这个这个代码功能来自动自动转换参数,转换参数带,然后呢这个它是如何自动转换的,针对于不同参数它的处理方式,以及呢这个它的一个接收效果,我们后面可以慢慢给大家研究哈。

那么我们先给这个传统方式来跟大家说一下,为什么它叫紧耦合方式呢,我们到这我们知道这个http s request它是哪个包里呢,是这个java x javx这个so light这个包里面的呃。

我们可以呃看一下,就是在我们当前项目里面的导入了这个依赖,这个依赖在spring mvc啊,这个零一里面呢有一个叫做呃java x呃,这个so light一篇,那么它是什么。

它就是其实嗯就是我们这个htp sol request对象的来源就是来自于这个包,而我们知道这个j s p a p i和这个so ea i呢,呃在我们这个tom cat里面其实就已经包含了。

它是在运行的时候才取消的,在我们当前项目里面编码的时候呢,是只是编码的时候需要而已,在运行的时候呢,这两个扎包直接由tom cat或者是服务器来给我们提供啊。

呃那么第一种解耦合方式呢就是要通过这个htb so request对象,这个时候呢我们在项目中spring mvc仍然是要导入什么,仍然是要依赖或者是导入这个so light扎包的。

那么也就是说我们的这个supremvc,跟我们这个so let炸包之间的耦合度比较高,你需要导入它才可以,这就是我们所说的一个解耦合方式,而下面这个松耦合方式就是不用这个htt so request。

在我们编码的时候呢,压根我们就见不到这个h tt so request这个对象,这个雷和对象,那么直接就是变成什么呢,直接就是获取参数了。

那这样的话呢我们super m v c跟这个javx so let api这个jb呢,他们之间就没有什么耦合度,这就是我们的一个叫做解耦合方式参数初步。

同时呢解耦合方式参数注入呢在写法上其实也更加简单啊,那我们就来写一个写一个来一个呃,public嗯,反复类型为string,string,起名叫做get data dt get pl来,这是获取参数一。

然后呢在这里面呢呃我们要是想获取这个参数的话呢,在这个参数列表里面,我们仍然可以添加这个http soul request对象的。

那同时呢我们也可以添加什么http so light response对象的a r e s p,也就是说在我们这个呃spring mvc这个这个ctrl层的一个处理单元里面。

我们是可以使用传统的这种http slide request对象,和传统的这个http response对象,然后用它去处理请求,用它去呃这个技术响应,那处理响应也是ok的,是没问题的。

那么我们可能暂时用不上这个对象是吧,直接测试一下这个请求参数,那假设我想在这获取这个请求中的这个呃这个use name和password,我该怎么办呢。

就直接这个ie q对象去点get这个perimeter,然后写上这个呃这个user name诶,变成这样子,username,然后再来一个iq点,get perimeter。

再写上一个p s w d password是吧,接受一下这两个参数啊,然后呢我们在这输出一下吧,那把这两个参数给拼到我们这个字符串里面来展示一下就可以了,然后再来一个password啊。

然后return return这一块呢我们想跳一面吗,如果说不想跳一面的话呢,我们还是可以参照参照我们之前这个呃这个control里面诶,怎么写出来了,这个ctrl这个test rest v里面。

我们把这个ctrl改的改成rest control,这样的话呢我们返回这个东西就当成文字,直接想一个浏览器了,这个rise control这个注解哈,我们在后面那个在那个阿贾克斯在一部那一块啊。

杰森杰森格式字符串一块的,我们会讲一下,暂时你知道加上他之后,当前这里面所有的处理单元都是直接返回啊,这种这种这种东西直接当成文字了,不是当成路径了哈,这个大家先别着急啊。

那我这块测试我们暂时引用这个吧,at rest control吧,呃我们这块直接返回什么,返回一个叫做随便返回一个文字吧,叫做gpr嘛,get pl。

你这叫做这个s u c c e s s叫做成成功的获取参数了,再给他来一个请求路径,叫做request mapping,请求就是入侵这块呢,我们给他来一个叫做斜线test。

就是这样想叫做get data get pero,那就是获取参数通过什么呢,by啊,by这个r e q e s request,通过requests随想来直接获取我们这个参数。

那我们试一试写一个再需要来一个页面,然后请求一下我们这个ctrl j ctrl怎么放这儿了,我把它拖到这个ctrl里面来啊,要不然可能我们这个spring mvc这个注解嗯。

spring mvc的这个boss描,他扫的是我们这个control,你要放到那个位置,可能扫不到了是吧,还是给它放到这来吧,这个带不带点度,这都无所谓哈,那我们接下来写一个风表达吧。

在这块来一个什么来一个叫做呃data page啊,这是一个数据页,然后就是这种form表单,我们随便搞一个吧,来ctrl c拿过来放到我们这个data配置之中,随便搞一个放表单,呃,至于是盖的方式。

还提这个什么方式都无所谓了,这个应该是直接写成一个叫做而已,这个br e q e s把request通过request方式请求,然后这个请求应试路径这块直接写成我们这个叫做呃。

get pm by request这个斜线不要加了,加斜线就要加上下文路径是吧,呃至于请求方式,get post这都无所谓,只要把参数带过去就可以了,而且这种参数带回去。

跟我们当前这个请求方式是不是restful风格知识的无关,无所谓,你是rise风格支持的也行,不是rest f风格支持的也行,无所谓的,那那么我们就用普通的方式来提交点呗是吧,准备两个参数。

一个是来一个in,来一个input,type等于text,然后呢这个value为username诶,不是value为username,是这个name username对。

然后再准备一个pass word,然后name也为这个pass word这个名字一样了,可能有冲突,但是应该也没事啊,我们测试一下看看行不行哈,那么这个form表单准备好了之后。

那么接下来呢我们重新更新啊,重新刷新部署一下项目,然后在这呢我们呃访问我们这个叫做data page,点js p回去数据就过来了哈。

把这个日志呢先给它清掉,省得有干扰是吧,来一个you name为张三,密码是123456,然后来一个by request,哎,看不保存,get parrorequest success。

然后you name和password都已经过来了,然后大家在测试的时候先不要着急用中文哈,如果用中文的话呢,呃中文的话可能会有这个乱码问题,再来一个123456,然后再来一个by request诶。

中文既然暂时没有没有哦,应该是get方式,是get方式,应该默认就没有了啊,top g理好了呃,但是你用中的话还是可能会出现乱码乱码问题,咱们后面再说,现在先不管它。

那么这个是一个通过传统的request对象来获取数据,那我们就搞定了这个传统request对象的话,那你就就就我们之前怎么在soviet里面获取数据,你就在这块怎么用就可以了。

呃那我们说用这种方式好不好呢,不太好,为啥不太好呢,它比较繁琐,比较麻烦,可能现在参数比较少,那你通过调了两个方法获取就ok了就可以了,但是如果说后面参数比较多,而且参数结构比较复杂的时候呢。

我们通过这种方式呢会给自己增加很多的代码量,而且呢它和我们这个斯维特耦合度啊,他们这种关联性太强了,不建议,那么我们还可以怎么这个呃注入参数呢。

来把这个给他ctrl c复制一下下面这个get pm 2吧,然后在get pad 2里面呢,我们就不用这个request对象去获取参数了,哎这些都不要了都不要了啊。

你要获取的参数无非不就是一个eos name和password嘛,对不对,那好那我直接才会写两个变量,string string也user name,再来一个string password,好。

直接这么写就可以了啊,那我们的spring mvc在处理这个呃,在处理在调用这个呃这个这个control层的一个处理单元的时候呢,它会有我们这个处理器适配器自动的将什么自动将。

它会检测你这个参数的什么参数列表里面这些参数名,然后这些参数名呢它自动到这个request对象里面去给你自动解析出来,解析完之后呢,在调用这个get的pm方法之前,把参数给你注入到这个参数列表之中。

就不用像我们现在在写这么多了,你直接把参数名往这一放就可以了,然后这个请求应试路径这块呢,大家需要注意一下,对,就是那凭什么要把我们这个呃这个form表单我再来一个吧。

来给他ctrl c ctrl v呃,再来一个来一个好人标签吧,来个hr好人标签,来一个闪光剑吧,哈这个叫做这个是解耦合方式,就是no request,嗯就是没有request对象来进行一个处理它。

然后请求方式这块是叫做get pyon by arg name,就是通过什么通过这个ug是参数的意思啊,通过参数媒来获取你提到提交的参数名,不是use name和password吗,对不对。

那好那我这块呢也是一个usname和password,他根据这个名字相同的参数名就自动给你放到这个参数列表上了,我们在这个ctrl的一个处理单元中直接可以使用它就ok了。

这都能够达到这个效果吗,我们重新部署一下啊,看一看能不能能不能达到这个效果哈,在这儿来进行一个刷新,刷新完之后呢,反正随便写成一个张三,然后再来一个123456,然后来一个no request走嗯。

不保存也成功了,看看后台有没有成功接收诶,也成功接收了。

那么这个就是我们spring mc中非常重要的一个知识,就是解耦合方式注入参数,这里面可以直接用这种形式来接受参数了,那如果直接用这种形式来接受参数的话,那它一定要注意哪一个事情。

一定要注意哪一个是这这个这个这个有一个注意项,注意项就是这个参数名就是我们这个处理单元,处理单元的这个呃参数列表中的这个参数名,必须和这个请求请求中的这个参数名一致啊,参数名一致哎,如果不一致的话。

那就不好使了,我们可以试一试哈,假设我们前面这个t叫这个数据这个password哈,呃它不叫password,这块叫做p w d,如果叫做p w d的话呢,那么我们这个在呃处理器是处理器。

是这个适配器在调用的时候呢,因为这个参数名跟我们这个参数列表这块就不一致了,那我们这个password可能就没有值了啊。

那真的是这样吗,呃我们回到这儿来试一试哈,这个修改的是一个js p,我们直接刷新就可以了,在这写一个张三,然后后面写成一个123456,然后一点no request一提交,看看后台。

你会发现这个password它就是一个now,说明这个password并没有给我们成功的解析啊,那假设这个时候我就就想用这个不同的名字,就想把这个p w d来给它映射到这个pass word上去。

那这个该怎么办呢,我们这块可以用一个注解叫做at,一个叫做呃,这叫做呃。

这个做的这叫做at request a r e q u e s t,request a q u e s t request paro的一个注解,然后在这个注解名录里面写个什么,里面写着一个p w d。

呃,意思就是我这个参数啊,在解析的时候呢啊解析的是我们请求中的哪个参数名呢,是通过这个名字来找到的,如果说请求中有个参数名为p wd,那就把p wd这个参数值呢给我们复制到这个string啊。

这个password上去,那么这个时候呢就做了一个这个名字转换的处理,看一看这种情况可不可以哈,呃我们再次呢在这块儿来,说一下处理完之后呢,我们再回到这儿来呃,还是在这儿来一个123456。

然后一点test no request eba,看看这回有没有a就有了就过来了,那么这个就是一个at request parrom这个注解它的作用,顺便在这块跟大家说一下哈,嗯那么然后再来往下看。

在这种结耦合方式注入这块呢,还有一个什么好处呢,就是假设哈我们这个password这一块在我们实际的使用中,它并不是一个string类型,假设它是一个int类型,那如果是一个类型的话。

它能不能给我们自动转化呢,而我们得到这个form表单这块在提交数据的时候,就算你放的是数字123456,那么它也是以这个字符串文字的形式去提交的,那这个时候如果文字形式提高的话呢。

但是我们参数列表这块它是一个int类型,它会不会帮助我们做一个简单的自动转换呢。

我们可以试一试哈,呃这个呃这个应该重新部署一下项目了,之后呢我们在这儿再来得刷新,它刷不出来都行啊,这个gsp这块没啥变化,张三然后来一个123456,再来一个no requests。

看一看后台这块呢它也是成功的,能给我们转换成int,但是转化他也没有给我们报错,对吧,哎呃那么那如果说我前端这块装的这个数据哈,假设放的是这个东西,放的不是这个123456。

假设放的是a b c d e f g,你这个玩意儿是没有办法解析成数字的,那这个时候我再来一请,求我们看一看后台直接就报错了。

什么意思呀,就是呃他报了一个number format exception,就是这个string这个东西是没有办法可以转成一个int类型的,这个其实就是什么,其实就是处理器适配器呢。

在检索这个参数的数据类型的时候呢,给我们直接用什么,直接用那个integer类pass来给我们解析的,然后呢发现这款解析不了,他也就报了这个异常了,就做number for my exception。

那就算这个转换不了,那那我们在填写参数的时候呢,在这块儿注意一下也就可以了,至少我们在这块呢这个也演示出来了,就是我们这个spring mvc关于参数注入的情感支出,第一个就是它简写了。

你要什么参数直接在那写,就可以了,第二个就是呢它可以进行一定的这个数据,一定范围之内的一个数据转换,当然这个数据类型转换这块我们后面还会再讲一下,因为这个还涉及到一些日期类型。

那么这个日期类型在使用的时候呢,可能啊这个要稍稍复杂一点,它转化起来可能会稍稍麻烦一点吧,然后那么这个是我们这个spring mc中比较重要的一个参数,注入这一块就已经搞定了。

搞定之后,接下来我们学什么,学的就是这种结耦合方式,各种各样的参数它如何注入进来啊。

系列 3:P79:【Spring】SpringMVC_注入POJO类型参数 - 马士兵_马小雨 - BV1zh411H79h

好我们继续开始讲这个呃supremvc这个参数接收的问题,以及参数参数注入和接收的问题哈,呃刚才讲的一个解耦合方式和所解耦合方式和解耦合方式。

那么接下来呢我们主要讲一下这个解耦合方式里面的一些细节问题哈,在这块主要讲这样几个大问题,第一个问题呢就是我们的一个p o g o类型技术参数,第二个就是关于一个日期类型的一个转换。

然后之后呢第三步呢就是我们的一个呃list集合呃,接收这一块,那还有第四个就是我们的一个map集合接收这一块,然后第五个问题呢就是我们的一个关于编码处理的一个问题。

我们先做这个事儿,叫做p9 来接收参数,那这个怎么来做哈,嗯打开我们这个呃,呃我们当前项目里面,这里面有很多的controller,还有很多的这个页面。

那么我们可以暂时把这些无关的这些ctrl先给它删掉,因为这些相关的一些代码呢,我已经给大家留存好了,那我先把这些这个无关的页面和无关的这些ctrl圈给它删掉,嗯删掉删掉之后呢。

我们在这个mapper和service呢暂时我们也用不上,所以呢先给它删掉也是可以的,在static这块呢我们也暂时没有什么静态资源,我们接下来主要用来测试这个参数接收。

还有这个success jsp这块呢也是暂时也不用跳转是吧,呃既然没有静态资源的这个super mvc点插标中的这个静态资源放行。

我们暂时就不用了,嗯还有这个这个也就暂时就不用了,配置处理器映射器和配置处理器适配器,这一段其实就不用了啊,视图解析器呢暂时先留着吧,那么这个先往这一放,下面这个删不删都行,先扔着吧。

那么这是一个非常干净的一个最简单的一个项目,那接下来呢我们准备一个界面,一个普通的一个叫做i n d x index,点js一个界面,我们还是往这里面能放数据,然后接下来往哪里提交呢。

我们在这里面随便准备一个controller,叫做什么叫做r e c i v e receive,receive data这样的一个control嗯,怎么说。

然后我们在这个control里面呢来专门接收参数哈,我们再给它加上一个注解,叫做at at rest control吧,我们后面的测试呢,后面的测试呢通通在返回路径的时候呢。

我们都呃直接返回不返回路径了,直接返回文字,因为我们这块就别跳转页面了,我们只是来测试这个参数接收而已,诶这个关于页面跳转这块我们后面再说,然后接下来呢我们在这块来一个接收参数,接收参数的一个方法。

来一个public string,起个名叫做get data data啊,这个叫做buying,叫做p o j o对,就是通过我们这个一个java的一个实体类来接收我们这个请求的参数。

来一个at request map呃,给它一个路径就随便写一个吧,叫做get data,get data by啊,p o g o好,我们先写这样一个方法好,return一个success。

s u c c e s success,那么配置好占一个接收的一个接收参数的一个control的一个呃,这个功能单元之后呢,我们在页面上的准备一个form表单,然后呢我们在form表单里面呢放一些数据。

往这个处理单元上进行一个提交哈,那么在这呢我们随便写一个放表达吧,来一个f o r m来一个什么表达呢,可以来一个嗯,可以来一个person的一个表单吧,呃提交一个person的一个信息。

他的action呢为我们当前这个get data by pu jo,因为当前这个模块呢这个就别写信了,写信的话得写这个spring mvc啊,那个挺长一串的,我直接写成相对路径得了。

嗯后面再来一个metal,这个matter是get还是post无所谓哈,都ok没问题,所以这会就不指定了,呃里面有写一个上一个input,然后呢type等于一个叫做嗯submit,然后呢value不写。

他也会有个默认值,那么接下来呢我们想想想往这个control里面提交,提交一个一个人的一个人的性别啊,年龄性别等等一些信息,那就写呗,我们在form表单里面应该这么写,姓名呢比较简单的一个input。

来一个乘乘乘五个吧,先乘个五个诶,别这么写了,来一个p标签里面有i n p u t input乘五个,然后呢这么写a写错了,这应该是,p业乘务,然后里面的input不成这么写,in a tb好了。

五个p标签啊,每个p标签呢它会自带换行效果是吧,那好呃,我们第一个要提交一个这个用户名,那么一个人的姓名,那我就来一个内部属性,为什么内幕属性为显是叫做p name吧。

唉然后value只能从界面输入就可以了,然后再提交一个什么属性呢,提交一个这个age p age吧,啊ph这个值,然后姓名年龄啊,再来一个什么再来一个,那这个什么再来一个这个叫什么gender。

性别性别这块呢,我们可以来一个叫做type为radio呃,内幕为什么内幕为gender,嗯然后呢这个value值的为a,一加上这是一个男,哎这是个男啊,然后再来一个女性的一个性别啊,value为零。

这个代表什么,代表这个女哎好呃,再来一个什么,再来一个这个爱好爱好这一块呢,可能就比这个上面我们用的是一个单选框,选性别,下面这块呢我们来一个复选框,选什么,选这个爱好爱好这块呢。

我们用的就是一个叫做check value值,为什么value值为假设这个是一,然后这个叫做篮球,诶这个篮球足球,然后再来一个羽毛球,呃分别值为二,然后写一个三啊,这是一个复选框,但是得给它内部属性。

内部属性,这个为a h o b b y hob h o b b y,好背啊,然后这块也得是一个这些东西,内部属性内部为h o b b y,嗯好的嗯,姓名性别啊,这个是姓名呃,诶姓名年龄性别嗯。

这个前面还得加上这个提示哈,这个一个form表单,这个写起来还是稍微有点麻烦,姓名姓名年龄,然后这边是一个性别诶,冒号下面这是一个爱好,然后之后再来一个生日,那么这个生日这块呢我们写一个什么。

写一个也是一个text吧,然后呢这个内部属性为什么内部属性为b i r t h t h d y,birthday或者birthday,这个birthday就比较称比较官方。

birthday是口语化的生日,birthday是官方的就算了,就这个英文了嗯,那么简单写了一个form表单,基本上就把我们要提交的数据类型呢给大家简单的这个呃准备了一下,分别是呃字符串类型。

然后呢这个数字类型复选框,单选框以及一个日期类型,那么接下来我们把这个日期这些数据在后台这块接收一下,那么在接收这块我们可以怎么接受呢,就是以第一种形式来进行接收。

可以来个string的一个p name,然后再来一个string的一个ph,还有一个是专性的这个gender gender,然后我们再来看这里面这个真的这这些东西都是单个值,就是它是一个两个输入框。

它也是二选一的对吧,但下面这个复选框它是一个可以选择多个的,多个的话我们可以用一个数组来接手,那我们可以来一个string类型的一个啊,一个数组叫做h o b b h o呃。

a h o b b y后背也就可以了,这块不要写这个i e s啊,这块要跟前面的保持一致,我们试一试,看看能不能接受过来,hobbit除了hobby以外还有什么,还有一个是日期啊。

叫做ball state,来这回来一个叫什么呃,先用string b i r t h d a1 birthday,为啥先用stream呢,因为这个birthday这一块呢。

呃它这个转换起来可能会稍稍有点问题哈,然后呢,接下来我们可以输出一下这些参数分别是什么,分别是这个直接输出吧,2345嗯,p内ph呃,沾点呃,这个的一个a r a y s a rise。

to street,来一个h h o b b y后背,还有一个是birthday b i r t h birthday哎,好,那那我们接下来呢嗯做一个这个简单的一个介绍哈。

我们看一看能不能够成功的接收到的这些参数,我们试一试,这个呢应该没什么太大问题,因为我们刚才在讲这个解耦合方式,就是通过这种方式来实现的,但是我们发现的参数有点多啊,它有点麻烦。

这启动可能会稍稍花花一点时间。

行动成功之后呢,默认帮助我们打开这个呃这个index jsp了。

我们放点数据,被姓名小说叫做张三,先别用什么,先别用中文啊,用中文可能会有毛病,年龄为十岁呃,性别为男,爱好篮球足球,生日啊,生日写一个1993杠三杠三,随便写一个,然后一点提交查询。

我们看看后台有没有成功接收数据,这些数据也都接收过来了,好都接收过来之后呢,我们发现有一个问题,第一个问题就是你说这个日期好像没什么毛病是吧,对这个日期可能会有点小毛病,这个日期我们后面单独处理哈。

我们发现这个参数列表啊太多了,呃就是呃前面这块如果说嗯如果说这个参数有变化了。

或者t的数据有变化了。

那么面临的一个问题就是,我们后面在这个这个地方所接触到的一个参数,它的个数也得也得有变化,也就是说我们界面发代码发生变化的时候,我们后面的control这块也得跟着变化,这个呕度有点高。

那如何降低这个饱和度呢,就是我们这块儿可不可以用一个参数或者是参数列表中。

只有一个东西来接收前端发过来的所有参数呢也是可以的,那么怎么接收呢,我们就要用一个比较特殊的一个啊这个这个接收方式叫做什么。

叫做用p o g o来接受,就是你这些东西我可以放到什么,这些参数可以在后台接收的时候呢,让他给我们自动的放到一个呃一个对象身上去,然后这个对象呢可以我们在呃这个后台中自己定一个类来封装,这些对象。

就好比说我们的一些实体类对吧,就像是我们从界面接受一个部门对象,那我我一个部门的信息,我这块就可以用部门对象来接受,那怎么弄呢,然后呢就这个com。m s b。p a p o c o在这个里面呢。

我们这里面假设都是一个人的信息嘛是吧,还来在这准备一个实体,叫做一个person的一个实体类,然后让它实现序列化接口,一般时间都实现序列化接口是吧,哎那么我们看一看,说这个接收参数不是有这么多参数吗。

那好那我在person里面就给他准备这么多属性,要准备这么多属性,每一个都给它来来分开一下,哎好准备了这么多属性之后呢,加上private修饰是吧,这些都该加就加就是了,加上private属性之后呢。

我们接下来给他提供一些get set的方法,我们先用自己的这个get get的方法来给他测试一下,后面的我们再给它改成插件呃,然后呢再给他准备一个全参构造方法,然后再准备一个呃,午餐无参构造方法。

为了方便我们查看对象信息,我们可以把它的to screen给他重写一下,重启完之后呢,我们发现哈这个person里面不是有这么多属性吗,那好那么我们在这个control里面就不用写这么多参数了。

我们可以写一个什么呢,我们可以直接写一个person p就可以了,唉person p就可以了,来给他a不要跑哎,导入一下,导入完之后呢,下面这块就没有这么多啊,我的参数列表中就没有这么多啊。

那我这块直接输出什么,直接输出这个p就ok了,呃在输出p的时候。

这块已经加上这个a。to好,那我们先来测试一下,现在我是用一个什么,用一个对象来接受什么呀,来接受我们嗯这个表单上的全部数据,那这个时候呢我们的这个呃spring mvc的三大组件有一个处理器适配器。

处理器适配器就会自动从request中解析数据,给它塞到我们这个pp这个对象身上去,那么能好用吗,该我们试一试,重新部署一下,回到这块来,这些天体的信息还在页面,页面没有改动哈。

所以呢我们直接等这个后台更新完之后呢,我们直接一点提交查询就ok了,一点提交查询,我们看一看后台的数据,他直接就把这些数据给我们,直接装到一个person对象里面去了,这些数据也就都过来了。

然后bird这块也就都ok了,那么这个也是super mvc非常强大的一个地方,那么如果说我们的参数列表是一个对象的话,它会自动解析什么会自动解析我们这个提交的这个请求中,它的数据。

它的数据中的这个名字哈,提交数据的这个内部属性就是我们的参数名,如果跟我们当前参数列表里面的某个对象的属性名一致了,它就会自动将这个参数名称给我们注入到这个属性,注入到这个对象里面去。

那这样有什么好处呢,好处就是假设我这块的参数变了,我多一个参数或者少一个参数,那么我这块用不用改动呢,这块不用改动,当然我实体类里面只要多一个属性或者少一个属性就ok了,哎所以呢这个是比较好的地方。

而且呢我们的参数列表这一块呢也会变得啊这样的更加简洁,那么这个就是一个用p o g o啊,来接受什么来接收我们这个参数的一个情况哈,当然呢后面呢还有很多很多其他的一些特殊情况。

我们现在这块呢继续往下往下讲解哈,那么在使用这个呃这个实体类来接收参数的时候,叫做叫做通过使用什么使用这个p o g o就接收接收参数时啊,这个一个注意事项,注意事项,这个注意事项是什么。

就是我们这个呃提交的这个参数参数名,参数名必须和什么呢,必须和我们这个呃这个p o g o的这个属性名保持一致啊,什么意思呢,就是凭什么你这块提交这个p name。

要赋值给这个psp对象的这个呃这个属性上去对吧,那就是为他们俩的名字的一致,为什么名字一致就可以给它赋值呢,其实底层就是用反射啊,就是这种反射这块呢接受这个参数名参数名单了。

然后再通过反射获取它这个字节码,再看看这个字节码它的哪个属性名跟这个是一致的,就跟哪个属性赋值啊,所以底层就是用反射来封装的嘛,那就会面临一个问题,那你说我们要是给这个person p属性赋值的话。

他要给这个给这个属性赋值,它是会走这个呃这个set name sp name这个方法呀,还是直接访问我们这个属性呢,那么我们可以在这个set name这个方法这块,我们可以简单输出一句话,输出句什么。

输出一这个set name就行了,呃如果sp nm执行了,我们就知道了它是什么,它是在走这个,他是在走这个set方法,如果说没有执行这个set a p e name的话,那就说明他直接在访问这个属性。

那么我们测试一下,看一看它到底是走什么呢,到底是走哪个东西啊,测试一下,先搞定之后呢,回到这儿来,然后再来提交,我们看一看他走的是这个sp nm这个方法。

也就是说明它底层是用反射来进行对数据进行封装的啊,在这个自然依据哈这个spring mvc底层底层是使用通过反射,通过反射给什么,给这个叫做呃参数列表的属性赋值,但是呢它是使用反射的这个直接访问属性。

还是走散的方法呢,它是通过什么通过这个set方法来设置什么设置属性值的,唉不是嗯啊这个不是直接什么,操作属性,那好那如果既然它不是通过直接操作属性,那么如果说我们在这里面把它所有的属性。

这些set的方法都全给它干掉。

只要你干掉之后,它会发生一个什么事呢,他还能他还会给能成功的给这些属性赋值吗,来我们再来测试一下哈,还是需要在这块重新部署一下项目。

然后我们等它重新部署完毕之后呢,我们在这里提交一下查询哈,再来一点提交,我们看一看诶,你此时你会发现诶它这些属性值就都没有了,也就是说当我们要是把这个类里面的一个set方法确定干掉之后呢。

它的属性值复制就会失败,他就认为你当前这个类里面没有对应的属性,而我们没有对应属性的时候呢,就没有成功往这个对象的属性里面注入一些值,它就复制失败了,哎所以这一点大家一定要注意啊。

呃我们这个这个p o g o的po j o的属性值属性啊,一定要什么,一定要有这个set方法,要不然就会可能就会这个设置失败,那就会这叫做接收失败,唉这个还是比较好理解的哈啊这是一个。

那么我们在呃这个就是一个通过通过p o g o来接收参数,但是在通过g p o g o参数接收参数时呢,还会有个小问题,还有个什么小问题呢,这个是我们下一期就跟大家说吧。

系列 3:P8:【多线程】锁的细节2:偏向锁启动与偏向锁未启动 - 马士兵_马小雨 - BV1zh411H79h

这个细节呃。

下面我们来聊下一个细节,就是什么叫偏向所启动和偏向所未启动。

这个认真听啊。

来看这里作为偏向所来说,大家我想问大家一个问题啊,我想问大家一个问题呃,我先问大家第一个问题就是。

提问吧,按照提问的方式啊,提问式的这样的东西有这么几个问题,你弄明白之后呢,你就知道什么意思了,我先问大家一个问题,为什么,为什么有自旋锁,还需要重量级锁,怎么打开,你想想看。

我已经有自旋锁了,我自旋锁在用户空间我还是轻量。

我比这个重量比较轻诶,这个时候我为什么需要重量级锁。

还需要重量级锁,为什么为什么呀,原因是这个竞争啊,你得看具体的情形,比如说大家伙都在竞争这个马桶,好,少量的人在旁边自旋,你搁这蹲着,特朗普来了,自旋个14 八次的啊,可以让他等着,没关系啊。

再让他在让他在这里等着就可以了,但是你想想这么一个问题,如果你持有这个资源,花好长时间,你才能干完自己的事,要持有这把锁时间非常长,其他人自选自旋的人数又特别多,1万人在这里自选,1万个县城在这自选。

大家注意自旋这件事。

它是占有cpu时间的,好自旋是战友,cpu资源啊,cpu时间等是吧,它是消耗cpu资源的消耗,这个设定较好,四圈是消耗cpu资源的,如果锁的时间长或者自旋,线程多,那么大家你想想看。

cpu资源会被大量消耗,你花时间就花在这些人的自选上了,执行那个空循环,花时间就花在线上的切换上了,全都花在这上面了,那这个是不划算的,所以在这种情况下会升级成重量级锁,重量级锁什么概念。

重量级锁里边有各种各样的队列,认真听啊,里面有各种各样的队列,你要理解这个概念之后,我后面给你讲reaction lock condition这一类的内容,你也能听懂啊。

不然的话我给你讲condition,很多人听不懂的,就是新新版的那个那个j uc那个锁的condition,重量级锁里边有什么呢,有队列听懂了吗。

就一object monitor里面是有各种各样的队列的,什么队列呢,比如说著名的wait set里边有好几个队列,有conditionalist,有entralist,weight s。

每个队列有它自己的作用,有的是用来做竞争的,有的人是用来做执行的,有的呢是用来做等待的,好这个到底是什么意思。

我们先来看源码,我们找到object monitor,where are you here,搜一下吧,这个object manager里面呢它有一个著名的东西啊,就是他就是wait set。

看他名字就知道这是一个set,这set是什么东西呢,是一个里边全部都在weight的一个一个的现场,所以所谓的重量级所是什么概念,重量级所的核心就在这重量,你所的核心在于当你持有这把锁的时候。

你想申请这把锁,一个县城想申请这把锁,像操作系统,操作系统给你这把锁,但是他会把把把把你这个线程给你扔到锁上面的一些队列里面,如果说我们等待的线程数超级多,1万个线程在那消耗cpu时间。

那我还不如给你升级升级重量级锁,升级重量级锁之后,它会做一个管理,做什么管理呢,凡是那些在那里自选等待,拿不着锁的线程,你都给我扔到一个叫做为set里面,维c的概念是我把你扔到一个队列里,我不让你执行。

把你给冻在那,freeze,你不需要消耗cpu资源,什么时候你想抢这把锁,是要通过我操作系统的进程调度,把你这个线程给你拿出来之后,你才有资格继续持有这把锁,所以当我们所升级到重量级锁之后。

有一些那些个锁他就扔到了weight set里面,它不需要消耗cpu时间,所以在锁定中超级激烈的时候,重量级锁会比自旋锁更合适,非公平的吗,你这就属于那个一知半解还得求关注的这种linux内核。

对于进程的调度,它叫做cfs,目前用的是这种调度方法,叫complete completely f,completely公平公平公平怎么说来着,completely fire哈。

我想到那个fire completely fire strategy叫呃完全公平策略,这个完全公平做策略呢路数非常深,我跟你讲的话就得讲半天,它并不是一个完完整的时间片分配。

而是根据你过去执行的时间片的一个比例来分配,你现在的调度过程,这没法没法跟你讲了啊,就讲到这吧好吧,总而言之,重量级所有自己的一个等待队列。

你不需要消耗cpu时间,所以在这儿呢,有等待队列啊,所有,拿不到锁了,进入等待回应,不需要消耗,19岁,所以这就是为什么有了自旋锁还需要重量激素的原因啊,不知道这个问题说清楚没有,有没有人有疑问的。

没问题吧,嗯,没问题,继续啊继续,来可以继续的给老师扣个一。

继续聊细节。

好我们继续,我们下来,下面来看什么叫做偏向所未启动,什么叫做偏向所已启动,好大家听我说。

我想问你,继续问你一个问题,看这个问题偏向锁是否一定,自旋锁效率高,我跟你说,凡是这么问的,那100%是不一定就是看你能不能想清楚他到底为什么,不一定就是偏向锁,为什么一定比自全球的效率高。

你偏向锁不是门贴上去不就行了吗,对吧,偏向锁什么时候效率高,多数的情况下只有一个线程执行的时候,偏向索的效率最高,但是如果有多线程,你明确知道有多线程在这里跑的时候,实际上它并不比自旋锁的效率高,好。

大家听我说偏向左不一定,首先答案一定是不一定在明确知道,会有多线程竞争的情况下,好在这种情况下,你明确知道这个资源会有多个线程来竞争它,那这个时候你还用偏向锁是完全没有必要的,为什么。

因为偏向锁肯定会涉及,所撤销,偏向组肯定是会涉及到所撤销的这个过程,那锁撤销这个过程一旦涉及的话,你用平白无故的耗费时间这个词能理解吧,所以你明确知道有很多很多先生在竞争,那你这时候直接关闭偏向锁。

你不应该打开偏向锁,你应该使用什么呢,你要直接关闭吧,应该直接使用自旋锁,好了,偏向锁不需要停战,没错,偏向所不需要停战,但是他撤销需要耗资源啊,把那条把大灰狼那那个名字条,你把它薅下来。

你不得耗点资源呀,大灰狼还会咬你呢,对不对,所以在明确知道有竞争,这时候呢实际上你没有必要啊,开启这个偏向火,好大家听我说,我们继续这vm启动的时候,启动过程会有很多,线程竞争。

你比如说最简单的我们往那个这边启动的时候,我要把那个一个一个的class落到内存,或者一个一个对象落到内存,在内存里头,要是不是要增强内存位置,要不要加锁,一定要加,所以在这种情况下,会有很多线程竞争。

明确知这就是明确知道啊,这个很明确,所以默认情况启动时,不打开摄像锁,什么时候打开啊,过一段时间再打开,等启动完了。

好所以呢这个东西在哪呢,这个东西在这儿就是默认的情况下,我告诉你,by as the locking start of delay,来我们读一下。

bias the locking start of delay,读一下啊,bias the locking that start up delay,什么意思,偏向左启动延时,大家注意偏向左。

默认的情况下有一个实验,这个默认是多少秒呢,四秒钟来验证一下。

验证一下,好看这里啊,我们刚开始new这个object的时候,注意我我我这时候呢没有,它默认是不启动偏向锁的,你还记得吧,他有个实验吗,四秒钟吧,所以你看到它扭出来一个对象的时候是001好。

来我们呢做一个最简单的,当然你可以通过参数来设置,怎么设置呢,就是像刚才那样,我可告诉你参数。

你把它设成start up delay啊,设成零好,这个时候他刚开始就会给你启动偏向锁好吧。

当然我我我所以最简单的就是让他睡五秒钟,五秒钟之后再来new这个对象,这时候偏向锁一定已经启动了,那我们来看一眼头像,15秒钟等着来,注意看这哥们儿刚才是什么,刚才是001。

现在呢现在nel对象是101,发现没有,同样是没对象啊,你睡五秒钟和不睡是完全有区别的,你们很好玩好了,这块能跟上的,给老师扣个一。

啊这没问题是吧嗯,那有同学说了,大哥你这个刚定出来对象,你就给上把锁玩呢,刚弄出来对象,你就是偏向锁状态,这啥意思,刚才我不是说了吗,这个偏向锁呀,其实后面会记录这个偏向锁的线程指针。

但是这里的指针你明显一看就是啥,全是零嘛,没有指针吗,空的吗,因此这把偏向锁叫什么呢,叫匿名偏向。

叫anonymous by locking,请跟我读anonymous,anonymous blocking,也要读出那种伦敦郊区音儿来啊,我看这里,所以为什么会有偏向。

所以启动偏向所未启动和偏向所已启动两种状态,就在于这在偏向锁没有启动的时候,你new出来的就是普通对象,001在偏向锁已经启动的时候是101,但他这种状态对象呢,由于刚开始还没有偏向任何一个县城。

所以他叫匿名,偏向,好讲到这里,没问题吧,讲到现在为止,这条线讲完了,这条线讲完了,这条线你看到了偏向锁没启动的时候,它自动升级为轻量级锁,这条线讲完了,这条线讲啊,这条线只要我们打开那个一看。

你就会知道上线要锁了好,还有一条这条线,这条线其实非常简单,如果在一个偏向锁状态,有可能直接升级成星链锁,什么时候呢,你偏向你偏向锁的时候,就把这个线程直接掉了,wait方法直接掉了,wait方法。

那二话不说,你轻量级锁不可能让你wait直接进入重量级锁状态,很简单。

好了,既然是匿名偏向这种匿名偏向态,我把这个注意看啊,我现在是匿名偏向台,匿名偏向台,我上把锁,他一定还是偏向锁状态,只不过里边的值就不再是零了,而是指向了某一个线程,看这里101。

但是里边的那个值全是零,匿名偏向依然是101。

但里边已经有值了,这是啥,已经偏向于我们这个may线程了,所以这里一加锁就是不再是匿名偏向,而是真正的偏向锁。

因此这条线我是不是也就讲完了,看这图,想到现在为止,这条线这条线匿名偏向到偏向左,这条线普通对象到轻量级锁,这条线偏向锁到轻度竞争到轻量级,这条线自旋锁到重量级,这条线重度竞争到这条线全都讲完了。

最后还差这么一个普通对象,完事之后呢,上偏向锁好,留作作业。

系列 3:P80:【Spring】SpringMVC_注入Date类型参数 - 马士兵_马小雨 - BV1zh411H79h

好我们用实体类来接收参数,这个小问题我们处理完毕之后呢,接下来我们开始继续往下去弄哈,这个关于日期类型的一个转换的问题,呃那么这个日期类型转换者是哪一个呢,就是我们目前在诶这个这个可以先关掉它。

我们目前呢在这个呃页面上所提交的这个参数呢有一个呢呃不太正常。

就这个birthday这一块,这个boss date这一块呢正常来说不应该用一个string来接受。

我们应该用什么,应该用个date类型,date类型的对象来接受哈。

嗯这块应该用什么,应该用一个a选中,它,应该用一个date对象的类类型的对象来接受,然后呢这个概率算的方法这块呢我这个时候我就使用loop插件吧,来一个at all arctor。

at no arctor,再来一个at da d d a t,然后上面这些没有用的,这个要好,那么呃我们在这块呃,把这个属性改成birthday之后,那么可能就会面临一个问题,我们这么做吧。

我们先做这个事,就是假设在这里面哈,我们不接受这个person了,我们就接受一下什么,我们单独接收一下他这个birthday,再来一个类型b r t b r t h d a t birthday,呃。

如果说我们在这块要是用一个string来接收的话,那毫无问题,因为之前我们也测试过对吧,直接就把那个文字呢转复制给这个字串就完事了,但这块如果我是要用一个date的话,他可能就会有一点问题。

我们把这个birth date给他输出一下,输出完之后呢,我们看一看能不能成功接收到这个birthday啊,或者是他有没有什么问题,还是在这儿我们需要重新的这个呃这个deploy一下这个项目。

这个回到我们信息比较这一页,好这块呢把这个信息的清掉,清掉之后呢,我们在这块再来一点,这块是1993杠三杠三,然后再来一个提交,你会发现此时就有一个400错误了。

什么错误呢,来看这哈,后面出现了个什么东西,就是呃他这个cannot convert value of java,long string to required tape java util date。

在这就他没有办法把一个string字符串给我们成功转换这个date,为什么有些能转换,有些转化不了的,像一些基本数据类型啊,它转换起来还是比较容易的,但是这个日系类型的转换起来可能会稍稍有点麻烦。

为啥有点麻烦呢,他没有办法直接把这个我们在页面上呢所填写的这个文字信息的,给我们转换一下,那怎么转换呢,我们可以呃,我们可以指定一下它的一个转换规则,就是告诉哈就是我们前面接收这个字符串。

我们用什么模板来进行一个转换,我们有两种方式可以进行一个转换,就是把前面这个字符串转一下,怎么转呢,第一种方式在这块加一个注解,然后通过这个注解来定义一个什么,来定义一个pyt模板。

这个模板里面呢就代表的就是这个字符串转成日期类型的一个模板,这个模板我可以这么写,这个这个mm是大写大写m m是月哈,如果你想加十分秒的话,那你在后面接着写这个h是冒号m冒号s就可以了。

但是目前这个日期好像只有这个年月日。

没有十分秒对吧,那我就直接连日就可以了,前面这块呢前面这块呢我们在这输入的时候呢,你就按照这种格式就往里放就可以了,那么这个时候加上这个注解之后呢。

那么spring mvc就知道了哦,他要用这种用这种格式来给我们把它给关掉,呃,要用这个啊这种格式来给我们解析这个字符串并转换这个date对象,那这个时候好用吗,来我们试一试看看行不行啊。

好再来一点提交查询,哎你看这个是继过来了,1993,然后呢这个呃3月三日就继续过来了,那那这是一个关于日期的一个转换,这是日期转换的第一种方式,但是你但是我们这个东西它好像并没有。

如果是直接一个date date类型的数据发过来,我们在这块呢这么一弄就可以了,这是第一种方式哈,呃这个给大家做一个截图吧,我直接把这个给你。

你control c复制一下呃,扔到这个日期型转换这块注解方式,其实这个是一样的,改不改的,改一下吧,再扔个截图啊,那么除了用这种方式以外,这个我们说呃我们这个数据接收的时候呢,是用一个对象来接收。

如果是用一个对象来接收的话呢。

那么我们这个接收的方式这一块,可能嗯这个这个这块我们要写的是一个person呢,它是一个person p诶,怎么跑下面去了,啊它是一个person p诶,那如果是一个person的话啊。

那么呃这个时候我们这个bd在在这儿呢,如果在这的话,能够成功的接触这个数据吗,是吧,我们再重新部署,清空之后再回来,好我们再来一点提交查询看一看,你看他又错了,还是这个原因。

就是这个person or project person啊,就这个这个person这个对象里面是什么呢,哪个属性的birthday这个属性呢,他已经拒绝了这个值了,为什么拒绝呢,那这时候怎么转换呢。

把这个注解加这看一看看行不行啊,然后呢还是一个pattern等于一个嗯y y y y杠mm杠dd哎,把这个注解放这放属性上看看行不行啊,一个是直接放这个参数列表上,一个是放属性上。

看一看这个o k这个是放在属性上,我们看看o不ok,这来查询看一看,唉这也是ok的,也是转换过来了,那就说我们这个as date for mt可以放于呃这个参数列表。

也可以放于我们的这个注解哈,诶怎么说他了呃,无格式粘贴可以用于这个参数列表啊,啊这个方法参数列表列表和什么呀,和这个呃我们的一个叫做呃对象和这个和这个类的属性上,属性上。

那么这个方式一呢也是我们推荐的一种方式哈。

嗯我们这个再给他来个截图吧。

呃放到这儿来这儿了,那么呃除了第一种方式以外呢,呃我们是这种方式,也是我们推荐的哈,方式一王皓也是推荐的一种方式,推荐该方式,因为该方式比较简单啊,你一个注解或者两个注解就搞定了,哪里有日期处理的话。

那你就放那里弄一下就完事了,呃另外一种方式呢叫做自己定义一个叫做类型转换器,那自己定义类型转换器这块可能就会稍稍有点复杂了,那这个怎么做呢,呃我们在项目中自己手动定义一个类型转换器。

我们就不用这个注解了,再把它给它给它给它注释掉吧,注册之后呢,我们可以在这个项目里面,然后这个专门放这里面放上一个叫做c叫做什么,date to a string to date。

string to date co n v e r t。

不是convert,我看这个单词是a converter c n v e r t r。

c o n v e r t e r converter,哎我们自己定一个类型转换器哦,refactor realme下,然后在里面呢我们定义一个这个类型的类型转换的一个类。

然后呢我们告诉spring mvc,当你遇见spring,当你遇见这个spring想转换成date的时候呢,用这个类型转换器转换,那怎么告诉他呢,那么在告诉我们要把它变成一个类型转换器。

但是呢要遵循一个类型转换器呢它的一个要求,那我们可以让它去实现一个叫做c o n v e r,t e r的一个这个类型转换的接口,那么我们可以选择哪一个呢,这里面有很多一个是map adapter的。

一个是这个呃listener这个up,还有一个就是spring核心的呃,那么我们选择这个我们先选择这个spring核心的吧,选择spring核心的时候,这里面有一个什么,有一个泛型,我们先选这个看看。

对不对哈,泛型就是从哪个类型要转换成哪个类型呢,把这两个发型往这放就可以了,泛型写完之后呢,我们重写这么一个方,实现这一个方法叫做convert的一个这个方法诶。

o你会发现string source就是我们要转换的源头,date就是我们要转换成的一个目标对象,那么接下来就转呗是吧,那怎么转呢,那在这块呢我们可以给他来一个这个用什么new一个。

这个叫做也不用在这扭了,不是每次转换都需要扭,我们可以在这块准备一个嗯,private,private simple date for matt,对象叫做simple呃。

叫做date for mac的对象,然后给他一个呃,给他一个new一个simple date for mate吧,然后里面给他指定一个日期模型,叫做y y y y杠啊,mm杠m m gd d。

然后呢我们用这个date for mt去转换这个source啊,来date for mate点有一个叫做pass的一个方法,把这个source往这一放,它会给我们生成一个对的对象。

我们的目标对象这个方法它有异常,但是异常的我还不不能往出抛,这是重写这个接口里面的方法,所以呢我们只能在这块给他,the song the way to cheat一下,那如果说转换正常了。

我们就把这个date呀给它干嘛呢,给它向上返回就可以了,我们可以把这个date对象声明在这date对象那个什么来解题,等于等于个now,然后呢如果转换正常的,就给这个data赋值,如果说转换异常了。

那么他就什么呢,他就这个嗯,他就这个呃出现就被就走这个catch了嘛,然后我最终return d如果成功转换了,那么就是一个正常的值,如果转换失败的话呢,走了cat,但是还是会正常返回,就是他一个闹呗。

因为这个data没赋值,但是我们可以在这手动抛出去上,the ro throw一个什么throw,一个new一个run time exception,然后呢在rap cl里面我们可以写成一句话。

假设叫做呃类型叫做呃日期啊,日期日期转换异常,让他好注册了这样一个转换器之后呢,呃我们自己定义了一个转换器之后呢,我们要告诉spring,就是你遇见这个日期的时候呢,遇见字符串转日期的时候呢。

你要用这个转换器来转换,那怎么告诉呢,我们要在这个spring mvc之中配置一下这个转换器能怎么装,怎么配置呢,首先第一步我们要配这个转换服务,配置转换啊,服务配置转换服务呢其实就是说明一个什么生命。

一个b哎,说明一个b,然后这个b呢里面有一个这个class。

这个class为这个类还挺长的啊,按照我们这来找哈,叫做conversion service factory b啊,这是一个哦,这是一个类型转换工厂。

类型转换工厂这类型转换,啊然后这个类名稍微有点长哈,拿过来拿了之后可以鼠标放上去,然后提示一下呃,more action,不能是create来b a n有没有提示诶,有提示啊,就他一回车倒下来了。

到这边之后呢,我们在这里面要配置什么,要配置它的一个转换的一个内容,就是用什么转换器来转换,给工厂注入一个叫做类型转换器啊,它有一个什么叫做converters啊。

类型转换器的一个属性,那么在这块给l给这个属性赋值啊,叫做配置类型转换器,播放器啊,然后通过这个property啊,然后来进行一个定义,有个converter的一个属性。

但这个converter是一个属性,它是一个什么属性呢,呃它是需要传这个一个集合,我们要把这个数据放在一个一个set集合里,再把这个set集合呢给它放进来,所以呢这块这个配置的时候可能会稍稍有点麻烦。

那麻烦就麻烦呗,在这边我们在写什么。

在写这个标签呃,按照我这个档上写字了哈。

我这边有个通过一个array数组设置,这么也行啊,哎试试吧,用这个array,那么我们要把什么,我们要把我们自己的这个类型转换器呢,啊这个一个一个类型转换器对象呢给它放到什么。

给它放到这个ari这个数字里面,那怎么放呢,写一个b呗,然后里面写成一个class class,为我们自己这个strain to date computer怎么写就可以了。

那基本上跟我们这个文档上也保持一致了哈,也就可以了,可以之后呢,我们就成功的在这块定义这类配置转行工,这叫做类数据转换工厂。

叫做数据转换工厂,那么这个数据转换工厂是谁用的呢。

就是用就是由我们这个叫呃叫做处理器适配器来使用的,就是我们三大组件里面这个处理器适配器,那处理器适配器在这种配置呢就是通过这个注解配置的一个注解,也就配置了我们之前的一个处理器,呃。

这个这个这个映射器和处理器适配器嘛,那我们要把这个告诉给处理器适配器能怎么告诉呢,在这里面我们通过一个叫做呃conversion service的一个属性来设就可以了。

然后这个conversion service这个属性使用谁,使用上面这个使用这个来给他一个id,叫做诶conversion service,那就完事儿了。

那也就是说我们下面这个conversion service呢自动走上面这个conversion service,就是把这个转换服务注册到我们这个这个这个处理器适配器上去,也就可以了。

那这个时候它就会自动给我们进行数据的转换,但是这种方式有点麻烦,第一个它是有点麻烦,第二个就是如果我们注册之后啊,那这个日期类型相对来说就在这写死了,那如果说我想带上十分秒怎么办,对不对。

所以这块呢我们不是十分推荐这种方式,略麻烦,然后呢又又又又不是那么特别灵活对吧,但是呢我们还是作为一个知识了解一下,测试一下哈,呃重新部署项目,这回呢我们再来测试一下,回到上一页呃。

然后呢再看这个control这一块,这个person这块呢,我们已经把这个date这个注解,我们看看这回能不能够成功的封装数据一点提交查询诶,你看他也是可以的。

那么呃我们关于这个时间日期的一个转换这一块。

系列 3:P81:【Spring】SpringMVC_注入List类型参数 - 马士兵_马小雨 - BV1zh411H79h

日期类型转换这一块呢我们给大家介绍到这里,应该就是足够我们使用了哈,那么接下来我们说一下第三项,就是我们一个集合接收参数的一个问题,那这块呢我们举这个例子。

举个什么例子呢,就是呃我们现在现在这个呃这个人这里呢有一个这个转换工厂。

这个暂时不要了吧,这个演示一下就可以了,这个也不配置了,然后我们这个呃date类型转换这块呢,我们还是用什么呢,还是用这个,这就不要了嗯,还是在这个p o g o上呢,这样可能简单一点啊。

那接下来我们举这个例子,举个什么例子,就是这不有个人吗,假设人养了两个人类,人养了多个宠物,那可能养了一只猫,养了一只狗是吧,还养了一只老鼠是吧,哎那么呃我们该如何接收更多的数据哈。

假设我们在这个页面上嗯。

在这个页面上呢再录入一下这个人啊,养了两只宠物啊。

那这宠物呢可能有一只,也可能两只有多支,那我们这块呢可以来个叫做宠物,从,然后呢它有一个宠物一啊,就是第一只宠物,第一只宠物呢我们在这块需要录一个宠物的这个名字和宠物的类型。

我们可以来一个嗯in input诶,怎么写成这个样子,input哎,然后呢type就直接写成text就可以了,然后第一个叫什么name为呃,先不写name先不写。

然后宠物医的这个名字从一嗯这个叫做嗯叫做名字,然后呢呃再给他来一个呃这个类型啊,是猫啊还是狗啊,这些东西再来一个这里一个input input,然后再来一个tape v嗯,这个也是为text呃。

我们先录入一个宠物医,这是第一只宠物哈,就是宠物的名字,然后正好再来一个内部属性,我们可以来一个pet pad,这个叫做tap宠物类型,那如果说我现在后台直接接收一个宠物的话,该怎么办呢。

我们可以在这个ctrl层里面呢再追再追加一个参数。

再单独接触他们两个,我可以这样来做,我可以单独的在这个po 9里面再准备一个什么类的。

再准备一个pet一个类,然后呢给它加上一个叫做at,art structor at no,structor at data,然后呢接下来在这个让这个pad去实现我们这个序列化接口。

s s e i序列化接口,准备两个属性名,private stream,加一个private street,然后pet type,然后呢我们用这个对象,用这一个pet对象来接受什么。

来接受前面这块可能会去传过来的一个关于宠物的一个信息,pet pet,然后呢我们在这块唉输出一下这个pad,看看能不能够接收过来哈,同样的,那么这两个参数的名字跟什么呢。

跟参数列表里面这个对象它的参数名字保持一致了。

那一致的话就会把这个数据呢封的到这个pad对象身上去,我们看一看能不能够封装进来哈。

那之后呢我们回退一下。

然后重新刷新一下这页面哈,来看一看姓名啊,这就写张3年龄十岁呃,性别随便给他一个把爱好,生日1993杠杠一杠一杠一杠四也行呃,第一只虫姓名叫做呃tom,然后类型的是一个cat。

那是一个汤姆猫,然后一点提交查询,看看后台呃,它确实能够吸收到这一个pet了。

那好那假设这个时候呢人不只有一只宠物,它又来了一只宠物。

再养只宠物,那怎么办呢,那可能就要在这块录两只宠物的名字,那再来个宠物二诶,也叫做pad type,那这个时候呢我们后台在接收数据的时候呢,这一直pad这一个对象就不行了,我们再给它改成什么。

改成一个list集合来接收类似集合里面组装数据类形式,什么是一个pet cat,让它叫做pet啊,这个path,那这个时候就会出现一个呃很大的一个问题,出现什么很大的问题呢,我们把这个来给他呃。

右击splate article,呃看这哈,就是我们现在这块呢这个参数列表里面呢有两个,这个可能要产生两个pd对象了,在提交参数的时候,它就会提交两次,然后pad type也会提交两次。

那如果这两个东西都提交两次的话呢,我们如何让他指定,这会形成一个对象,往这一放呢,再如何这个东西再形成对象,再往这一个集合里放呢,对吧,那么我们要指定什么呀,我们要指定往这个集合里放。

而且要形成两个什么,形成两个对象,那我们这个name这块该怎么写呢,这么写,首先写成一个p e t s,那就代表我要往这边,我要往这个集合往这个pass这个集合里面去放什么,不能呃。

这个集合里面呢会形成多个pd对象作为元素,那我们在这块可以写一个中括号,写一个零,然后呢打成一个点,意思就是什么意思,然后同样的后面这个也是再来一个p e t s pass诶,中国号,然后写一个0。

2哎,也是一个点哈,就是后面这个呃pad type,我要给它放到这个集合的元素啊,索引为零的这个元素这个对象身上去,那么他们两个他们两个就会封装成一个对象,这一个对象就会放到这个集合中,索引元素为零。

那下面这个也是类似的,就是一个p t s中括号,它的索引就是一了是吧,打个点儿是这块,再来一个p e t s中国号,它也得是个一了,然后再来打一个点就可以了,那么这样的话呢它就会呃在集合中形成两个元素。

这块指的是集合名,这块指的是元素,那个索引往哪个元素上去放,那好,那这个时候我们在这块遍历一下这个pass,看一看能不能够成功的获取这个数据哈,s o u t p e t s,我直接输出这个集合。

那这个时候呢我们再来重新来部署项目,重新部署完毕,然后呢我们在这块呢得刷新一下这个页面,因为数据多了嘛,我们只放这个宠物名哈,只测一个宠物名字了,一个是tom啊,它是一个猫,再来一个jerry诶。

他是一个m o u s e mouth啊。

一个老鼠,一个天查询出错了,说有什么错呀,no primary single,public constructor found,什么什么类似,no default construts at。

这应该是一个呃主要的构造方法,你这个类似集合这块呢,应该是我写成一个具体的一个集合吧,叫做relist,a realist啊,好呃,能不能说我这个这个类中哦,arno altera已经写了呀。

嗯然后我们看看这块名字呃,pad type,这个ok没问题,我把这个参数列表呢改一下,改成l list,好像不改也行呢。

我们看一看这个日志是怎么报的,那应该就是我这个参数列表这块呢,我先用这个俄罗斯试一试吧,看看用类是不是就好使了啊,把这个日先清掉,回到这儿来,回到这儿来嗯,再来提交一下,出来了。

出来之后我们发现一个集合,它是一个呃这个空的,这里面应该是有一点小毛病,我这里调一调。

把这个改成release也不行,那再改回list哈,呃跟大家说一下,为什么不好使啊,原因就是呃如果我们直接在这块用这个类似集合来接收啊,这个对象,这个对象呢在理论上似乎行得通。

但是事实上的supremc不允许我们这么做,我们在直接接触类似集合的时候呢,有两种方式可以处理,要么就是我们在后面学到的用一个什么,用一个这个json格式,用这个js把这个前面数据转成json格式。

然后呢传给他呃,要么就是要对这个类似集合再次进行封装,什么叫再次进行封装呢,就是不要直接把它放到这个参数列表里,放哪儿呢,我们可以放在这个person对象,呃,person这个类里面。

然后呢把它作为一个person类的一个属性来处理,这类中添加一个什么,添加一个a private,来一个list集合,然后里面写成一个p e t,然后里面写成一个p t s path,这么写。

这么写的话呢,呃那么呃我们就在参数列表中就不用再写它了,然后就不用在意它了,为什么不用在意他了,是这样的哈,我们前面这个pass是谁的,这个pass必须啊,这这就不能再输出了。

这个path必须是我们p对象的某个属性的名字,哪个属性的名字呢,就是这个属性的名字,由于这个属性是一个类似的集合啊,那么这个类似集合里面放元素的时候呢。

就通过这个哎这种放括号里面放索引的形式来把元素呢啊,给它注入到这个集合里面的呃,把这个数据呢给它注入到集合里面的,所以尾灯的元素索引为一的元素身上去,那么我们试一试这种方式。

看看能不能成功的接收我们这个呃类似集合啊,来我们试一下呃,在这呢重新部署一下项目,额部署完之后,我们还没有测试呢,我们在这块还得输出一下这个p点,get pts呃,就不要这行吧,这么输出也行啊。

这是单独获得这个pass的类似结合输出一次,这次是整体输出p整体输出p的时候。

他也会带上这个path这个集合,我们看一看此时能不能够啊,说到这个啊类似集合啊。

再重新部署一下吧,然后等它重新布署完毕之后呢,我们提交一下这个phone表单,提交一下。

提交之后我们看一看哎这回就可以了啊,你看这个类似这个person中就有这两个pet对象了,单独获取两个pd的相应输出,就是这样的,你说前面这些信息怎么没有啊,因为前面这些我们也没有在这块放纸诶对吧。

那么这个就是用呃一个呃这个control来接收啊,类似集合的一个这个数据哈。

系列 3:P82:【Spring】thymelaf模板引擎 - 马士兵_马小雨 - BV1zh411H79h

好了这块我没问题,之后,ok这是我们的这个web web开发相关的一些知识点,大家发现了这些知识点,我都是从官网里面截取了一部分,就是我认为比较重要的东西拿出来之后给你们讲一下,来给你们讲一下。

这个我刚刚大家已经发现了我的模板引擎非常非常重要啊,之后我们在开发这个项目的时候,也需要用到我们对应这个模板引擎相关的一些属性点,所以可怎么办,我们来看一下模板引擎应该怎么做,快来找一下sirleaf。

我玩引擎呢找一下啊,在外边开发这块注意了,一般情况下推荐大家使用我们对应的一个模板引擎好吧,而且而且你注意一件事,模板的模板引擎,大家看这个除了rest for a rest web服务之外。

你还可以使用marvc来服务动态页面内容,spac支持多种模板技术,frame mark和js p,当然要注意了,gsb这块我不知道你们在公司里面还是否会使用,现在已经没人用这玩意儿了。

大家想一下jsp它是啥东西啊啊翻译官叫啥叫java server配置吧,相当于说在这次页面里面我可以嵌入我们对应代码,java代码,然后呢可以把我们后台返回的数据动态呢显示到我的页面里面。

而我们在使用我们对应的一个模板引擎之后啊,它也可以完成我们对应的功能功能,所以他说了,所以model里面提供了以下模板引擎的一个支持,free mark la,好吧哈,simf还有这个东西。

目前用的最多的可能是simp这个东西,他做了如果可以,请尽量避免使用jsp,当使用了内嵌sorry的容器之后,会有几个已知限制,这块有限制好,但不管怎么样,建议大家不要再用我的js p了。

最好用我们的simrp这块问题来了,silip我应该怎么学,在我们的spring boot的官网里面啊,官网里面mark这么多,你们诶问一下你们在公司里面用free mark用多还是用生命用多。

free mark用多扣一,simplif用多扣二,都不要,l e g s p只做后端枪弹分离行吧,这块啊如果你用free mark多用用多的话,你就它其实也一样的,你可以看一下他官方网站。

就是那个文件名称后缀的f t l啊,它里面有官方网站,其实也就是一些去对应语法规则,你把这些语法标签掌握了之后就够了好吧,这降完就够了,呃都不用清水js p这这这js p现在已经不用了。

大家看到了这个文档里面都比较简单,其实里面有if else if是不是有一些逻辑判断对吧,同样的simillif里面也是一样的好simillive也也是一样的,把它打开,这是simplive里面。

就是说你用simplive的时候,你可以怎么样呢,直接用我们的html页面等会就行了好吧,它不需要形成一个单独的一个模板引擎,就是用在html页面里面直接进行嵌入,这个地方就是simp它的一个官网。

把simplip用于官网,所以这一块我把simlip这块给大家重点说一下,free mark,如果你们有需要的话,把free mark一个重点学学啊,那东西也不也不难,还是一样,从公告里面看就行了。

他说了,在早期开发的时候,我们都用静态页面,也就是html页面,随着时间周围的发展,慢慢引入js p页面,当在后端,当在后端服务查询到数据之后,可以转发到我们的jsp页面。

可以轻松地使用js页面实现数据的显示和交互,这4p有非常强大的功能,但是在此时boss的时候,而且还嵌入了他们开的容器,因此在某种情况下是不支持我们的jsp页面的。

如果以纯静态页面的方式会给我们开发带来很多的麻烦,所以推荐使用模板引擎,模型很多种哇,有js p fmark sief是用二代码写一个页面模板,然后呢也就值动态的可以写一些表达式。

这些值可以自动后台查询之后返回去,好吧,这是它这个图官网点图啊,说ta然后tm页面这是dollar user,要说这后面可以用我们的date数据,此时你用模板引擎之后。

它显示的数据就是什么叫hello张三,就这样的信息,所以就是说把我们的数据做了一个原生替换而已好,所以simon live啊,他学起来并不是特别麻烦啊,并不是特别麻烦,大家看simlif有些介绍。

官网刚刚已经给你们打开了,还是老规矩,我们从官网里面来进行一个查看,第一个先选一下下面的有东西啊,docs是道高温闪,但他们这块有很多,大家看到了,是不是有using simp,有三的对吧。

有三的下面都是三版本,之前还有用二二的版本,现在啊可能用三星的更多一点,我这里讲的也是三,你可以把这些文档可以在线看,也可以直接把它给下载回来,这块我已经提前先下载好了。

一会儿把分析出来叫u等于simp和同学看这个文档的时候,看的可能很难受,因为全部都是英文的啊,全部英文的嘛,所以这块也一样的,我给你们相应的匹配的找了一个中文的网站,自爆塔,什么离谱。

看看就告诉你这simplif一个例文,什么simalef有什么样的东西,这块都是写好的,但是我们后面如果要进行一个项目开发的话,这块你是必须要会的,所以这块我们先拿几个简单的东西来给大家演示一下。

他到底做了什么样的一个事情,可以看一下什么是离谱,这做的比较一个比较详细的一个解释,然后呢能顺便这狗能处理哪些对应的一个模板,网页发出来,来你们存一下,当然还有一些标准方言,如何构建一个虚拟杂货铺。

这块给大家说一下,它这个网站比较好好在什么地方,它提供了一个对应的一个呃样例模板,也是他给了一个项目,你做这个项目之后,拿过来之后可以直接进行运行。

我这已经运行过了,给大家看一下,这东西叫这vt t,大家之后呢怎么做,直接运行,看看对应效果啊,看对应效果,就这是他那个simp官网里面提供出来的一个呃模板的东西啊,已经使用了是吧。

地址地址地址端口冲突了啊,停掉,一九,修好了吗,等一下啊,ok启动好了。

听到之后看到了吗,是大家提供好的官方网址,product list是有这样一个展示列表,然后下面有一个order list,然后告诉你说你怎么来查看里面有什么的相关信息,再做一个展示。

然后返回返回use the home,什么东西,return之类的,就是他做了这样一个页面,你可以进行自己的一个查询,好自己一个查询,所以这块你可以下载下来这个代码,把这个代码运行一下。

注意不需要改任何东西,直接需要嵌入一个copx容器,它能运行了非常简单的一个方式,这是他官网里面给我们做的一个最基本的一个提供啊,最基本的一个提供,提供了之后,下面更多的是什么。

你要看一下这东西应该如何进行一个使用,它有一个东西啊,标准表达式语法,然后看他说了,第一个叫简单表达式,里面有变量的,有选中变量的,有消息的,有u22 的,还有我们的片段,有常量,有文本操作。

有算术操作,有布尔操作,比较和相等,才叫运算符和特殊符号,这边是不是都有,所以你在用的时候直接拿这东西来进行查看可以了,而且每一个点里面他这都给你做了一个解释,告诉你说你应该如何进行一个最基本使用。

每块都解释了,所以这里面代码你其实可以拿过来之后,直接嵌到你的html页面里面,直接进行一个查看,都非常简单,这是第一点,你要看看第二点我如何来使用我们对应sif,好吧,你往下翻翻。

翻到这块有东西叫属性,在熟悉这块告诉你们说,如果你想引入片段的话,你要用什么叫t h insert好或者t是release,如果你要用迭代片段的话,用t是意识,就是我们的循环条件的话。

提是if局变量提示object,提示位置一般属性a t t r好吧,特殊属性上有value和f s r c文本的话属于我们text,然后呢呃片段的话可以用个for a forgent。

然后还有个t是remove这帮用的这些标签,就是说以后我们如果要写页面的话,你可以怎么样呢,直接用我们的fm这个引擎直接往里面嵌就行了,非常简单,这个属于前端吗,呃不算前端吧,就你写好前端页面之后。

你可以自己做一个基本的修改,你懂我意思吧,好了,那这块我们怎么来做呢,怎么来做呢,也非常简单,下面文章里面我给你写了比较详细的一个模式,第一点你需要先引入我们的模板引擎,我把地址也给你站出来了。

就给up地址好,这是第一点,当你把这个地址写出来之后,你注意了,当你引入当前这个配额妹妹的一个依赖之后,问的一个依赖之后,而中文方式可以放到silive文档里面,可以可以,我给你们加一下中文。

挖地给它粘一下,以后下课忘了变哪去了,我直接打开一下,重新打开,好就这样吧,你们直接访问就行了,直接访问就行了,让大家看注意了,当你导入这个依赖之后,相应的它会有一个会有什么呢,叫same leaf。

然后properties,所以这块我们也可以做一个最基本的查看,怎么看呢。

这写一个叫sim t之外leaf jm r e f properties,打开之后你会看到它在哪儿,是不是指定好了,我们当前这个目录是一个timeless这个目录。

然后呢同时还会告诉你说这有一个点html的一个后缀对吧,所以以后你如果需要自己开发一个web项目的话,直接写html页面就行了啊,写html页面就写了,写完下面页面之后,它会自动进行这些数据的一个渲染。

把那些值给我们给填进去。

这样我也举了一些例子,你把这个看一下怎么使用啊,看这我写了一个非常简单的一个需求,说第一你需要在java代码里面写一些对应的信息,比如说这有个叫model相关的信息,这怎么用啊,让我们写一下试试吧。

先看一下第一个我应该怎么进行使用。

把它关掉了就没用,把拿过来,这儿有一个ctrl是my ctrl,这是lo hello里面加一些东西,因为这是集成mvc的嘛,所以直接用model就行了,model。

卧槽这加一个属性叫model第二代h6 ,然后呢逗号spring再返回这边合页面,返回页面之后再回页面里面,我要写东西写什么,这边先不要了,不要正好注意了。

你要想在html页面里面嵌入我们这个c6 模板,这你必须要加载一个标识,是告诉他你用的就是我们sim lip这样一个东西,怎么加点,表示高考里面也有一个明确表示要找一下嗯。

哪去了,找一下我们的页面啊,这有页面啊,这个记得诶没有吗,这没页面有换一个,我找一下啊,看着就这个东西,你把它给拿过来,把这个代码拿过来,他说c打完之后站到我们刚刚这个地方t标签后面。

站完之后就搞定了,此时在用的时候,你可以干嘛叫显示加点东西吧,消息刚刚,喂冒号后面加一个东西,就加一个p标签吧,啊这加一个叫t h冒号是叫text,赢的时候这是一个变量嘛。

所以用dollar符号括号加一个东西叫msg好,加完之后,这能做一个展示了,现在我们把当前这个应用程序启动一下,启动让他报错了啊,加一个封号,睡一觉中画中画可以吧,可以可以可以中画中画也可以。

把那鞋也可能稍微麻烦一点,来行动号之后,我们这直接返回一个哈喽。

看这显示消息为hello,bot。

是不是意味着我们刚刚后台写进到model里面的一个数据,已经被我们前端这个页面给查到了,这是私用公制谱模板最基本的一个使用好,最基本的使用,所以它并没有特别难,关键就是说我知道如何使用这些标签。

或者说如果使用这个贴纸标签就够了,你要来说所有的属性你都可以加t h冒号,但前提是一定要加上这样一个呃标识,告诉你说你要从simc里面进行一个引入了啊,这块很重要,懂我意思吧,下面来再接着看怎么用呢。

现在告诉你说simplif支持的一个语言表达式这块给粘出来了。

这块粘出来的信息啊,粘出来信息就是我们刚刚给你看的东西啊,从官网里面看的哪看的哎,嘿第四块是标准语法表达式里,每个里面表示什么意思,你要去边上的时候用dollar选出表达式的时候用星。

然后呢消息表达式用井号,这个下载的是一般在国际化的时候用的比较多一点,然后还有什么呢,选择我们的u22 ,用at符号,如果是片段的话,用波浪线对吧,你别告诉你有还有其他的一些曲折的方式。

你直接拿过来取就行了,循环怎么弄呢,一会我给你演示循环应该怎么操作好,同时下面还有什么,第十块,你记住了,第四个点里面告诉你说有哪些属性标签,你可以进行怎样的一个使用,这块东西,文档里面文章都写好了啊。

这张出来图说了,semitive实例演示,test表示文本的一个内容,value表示当前元素的一个值,ph就是表示什么是我们的循环操作了,if表示切判断,insert表示我们代入的那个代码块的一个植入。

然后呢fm表示定义代码块,object声明变量a t e r表示修改属性,那修改属性一般没人用啊,一般没人用,现在怎么做呀,来先看这个方,我把这页面直接站出来,说这这样写一个页面吧。

他们这里面右击另一个a t m a n c h y m e l e f转过来,二位二位扎完之后,大家发现了这个页面其实并不是特别麻烦好吧,81级第一导入这标签,第二告诉你说这是一个text。

you text,然后呢,这有个value,有个each,是不是循环,还有什么呢,我们这有test,然后object是不是各种变量的一个引用,这还可以做一些逻辑上的一个判断,是不是这意思啊。

而且这可以做一个循环这个东西,这东西并不难,关键是什么,这些数据来自于哪,这些数字在哪看,还是一样,你从你对应的controller层里面给它做一个最基本的返回,怎么返回。

再一个public three,这写一个sir括号,加一个at request,main括号c r e m e l e a f clef,提示y,加进来,加完之后是不是可以往里面写我们对应属性值了。

这是原值,你也没必要自己写,我这都写好了,把拿过来看。

c认为这样加一个属性叫model map map,这是少一个person slay是吧,我们建一个person类吧,又一个配置问题,t这定义一个class person,private就这样name。

prada int age by the stream,真的这东西都比较简单,然后写一个构造器,吴三的,韩餐的就加一个set get方法,再加一个突袭队,好了,这定义好之后,这个值不就有了。

ok当你这块写完之后,写完之后就ok了,现在怎么样呢,直接我这是弄好了,这边呃挺妙的哟,重启一下吧,重启一下,感觉有点像以前sars标签其实还是一样,不管是sars源有什么。

是不是有东西og n表达式好吧,你想一下你在学你在学那个js p的时候,g s p的时候有什么东西,是不是有个东西叫e r表达式对吧,还有一个叫什么叫e g g s t a r表达式对吧。

现在呢在thrust里面有个叫og n r,有人用微信号,相当于你知道死啦死炸死,很多同学已经不知道这东西了,好像现在里面就是用了一个t h,其他现在都是什么,就是c标签,p标签。

是不是这些标签用这个标签拿来用就可以了,就这样意思啊,对象导航图语言对,是这样的东西好了,这儿发完之后,我们这儿可以发送一个对应的请求,凭什么信息啊。

叫silit h y m e l e a f到,怎么摆放2p也是看这请到了吗,是不是这些相关的数据我已经全部都请求到了对吧,这块你可以跟我的页面的做对比,好做对比,对比之后你会看到这儿请求东西。

就是我们想要的那第一个这test什么东西,然后呢引入对应的一个值,把这个值给做一个演示,同时这里面还有啥页面了。

是不是还有我们对应的一个循环列表,而least等于啥等于啥等于啥,是往里面显示我们对应心就行了,好判断下是否为空,然后内部等于啥,a就等于啥,真的等于啥。

关键就在于什么呢,再说你在使用这个html标签的时候,你要知道这些属性应该怎么引用,这里面我们主要用两个标签,一个是doa开头的,一个是新开头的多少开头表示引用的是什么,是对应的一个变量值。

而c开头什么意思,是指的是我刚上面是声明了一个变量叫t h object,object里面这个对象里面的属性,你要想引用的时候,必须要用星来进行引用了啊,这是他们之间的一个区别。

像后面刚看到at的标签对吧,这东西我后面会演示的,在这页面你要会写明白我意思吧,好吧,你要知道这个标签应该怎么进行引用,看到了跟我们刚才一样比一样一样吧,是没啥区别啊,非常简单的一个实例啊。

现在之后好好看一下这东西难吗,不难吧,这sima leaf最基本的一个使用这块拆之后。

一定要自己做一个演示,这块来听麦同学扣个一。

能听懂吧。

好了,除了这个sim live这块之外,还有什么东西,我刚说了,还有标准表达式语言,比如说dollar变量使用新叫选择变量表达式,这两个东西在上面的时候都已经用过了啊,所以我们这不再演示了。

好不再演示了,但是你注意了,这个变量在使用的时候,它还有很多小细节在里面,什么细节,比如说这第一个我可以把我们的session里面放数据,就是说它可以获取到我们对应对象的属性和方属性方法。

同时可以使用什么呢,cd s mars local request response session,所谓的contest是不是这些内置对象里面的属性,我也能从里面取到,比如说这样我来做一个演示吧。

非常简单,打开我们的这里面。

在我们的请求里面加个逗号参数,逗号叫a ttp session session,加一个session点,set tribute,这写一个name逗号张三加完之后你也一样,在页面里面加一个东西。

一标签t h冒号test,这写一个叫dollar括号,session点叫name,用完之后呢,我们现在重新刷新,我们对于一个浏览器页面。

是刚才出来了吗,出来了吧,是不是那个对象里面的属性值也能可以获取到,所以它用起来比较灵活一点,比较灵活一点,你可以按照自己的想法,所以去进行一个更改好,这是第一个标准表达式,除之外还在干嘛。

它还提供了很多内置的一个方法,比如说days日17吧,debus数字吧,string字符串,object对象,array数组list集合30倍集合,map是被集合。

我还可以用这些内置的这些方法来做一些处理对吧,里面每个东西都解释了有哪些常用的方法,这块下面都给大家写案例了啊,都给他写案例了,下来之后,你可以把这些案例拿过来之后好好演示一下。

好看一下大概是什么样的一个效果,ok ctrl层里面怎么往里面复数赋值,放数据我也写过了,我也写过了,从拿回去之后好好看看,我都写的比较多,写的比较详细了,所以你有能力啊,把这些东西全部完成。

懂我意思吧,好吧呃,下午时间差不多了,我们大家来聊聊这么多,晚上八点钟我们还有课,所以一会儿我把这个文档给大家分享出来,翻出来之后,你先按照我刚刚写的那些文档,先自己去做一下操作,特别是作为初学者。

一定要做一下,哪怕你把代码复制过去运行一下,要用好,也要试一试,懂我意思吧,8年什么课还是charger smoot,刚刚没讲完,还讲什么东西,比如说国际化我们还没讲。

比如说我们的呃数据数据源还没讲好吧,以及我们估计今天晚上把数据源讲完,讲完之后,我们就开始讲源码,好给你们讲很多东西,所以一会儿把这个文档里面代码先做一个实施好,做一个演练,完了之后,我们晚上再接着聊。

好吧行了,今天东西难吗,觉得男同学扣一不难,同学扣二,难啊这还难啊,sn bot是不是一般不配置多数据源,我记得上一次是谁问我说呃,swibot是不配多配置那个额数据源。

多那个多数原配置总配是是你问的吗,冯生可以配可以配,我这儿给大家写好了,我专门准备了一下,专门准备了一下spring board数据源,今天刚学了数据源,找一下啊。

大哥看着spring boot多数据源的一个配置,我这都写好了,好晚上的时候可以给大家演示一下这个效果好,怎么来切换我们的数据源,这块都有,所以你们面试问到的一些点或者自己不会的点,这样都有啊。

可以随logo对,确实随着logo晚上看挺麻烦的,比s麻烦,需要用到three里面的l o p,先用到spring op,还有很多东西啊,这块我都写好了,晚上讲的时候咱们再说行吧,md是什么软件。

那这里面带一些格式啊,看起来更舒服一点,看起来更舒服一点,笔记传到哪里了,传到我们的get up上面去,我一会会把上传,会把上传,这样左右都会都会给你传上去啊,要这么对,哎,这也可以弹啊。

看搞一个maven的一个插件就行,好像是maven插件就行了,行了,今天下午咱们就聊这么多,晚上八点钟咱们准时再见,好同学们,ok拜拜,老师这个中文到哪找的呀,哈哈哈,中文文档,你你你你你找就行了吧。

这个这个百度里面都有吗,其实大家发现了,其实我现在不是在百度里面找,就你看到我们这些中文网站啊,他都在同一个根目录里面叫gtbook,我不知道这个网站你们有没有人看过叫gtbook,这个网站下去之后。

你们可以注册一下,好,可以注册一下,里面有很多的一些中文的一些相关翻译,这都有要注册啊,这只比较麻烦啊,这边东西比较多,我基本上起码需要中文档的话,都会从这里面搜,这边搜啊,剩下就行了,好了。

就聊这么多吧,晚上再见拜拜,对所有课东西都往上传,是的。

系列 3:P83:【Redis】常识介绍--磁盘、内存、IO - 马士兵_马小雨 - BV1zh411H79h

有一些常识。

常识常识是什么意思,常识不是你该炫耀的知识点,常识你必须要知道的,但是在这呢我们统一来说一下这个常识,就是首先在计算机当中。

数据是存在磁盘,数据在磁盘里的,那么以磁盘的维度,它有两个指标,第一个是寻址,寻址的速度是毫秒级的,然后第二一个是带宽,也就是说单位时间可以有多少个字节流过去,多大的数据量流过去。

然后基本上是g或者照这种级别啊,就是多少g或多少兆,几百兆或者12g这么这样的一个一个带宽速度。

另外一个就是内存,内存它有一个寻址。

它的寻址是纳秒。

10纳秒,那么秒这个时间单位里边儿秒,然后再往下小是啊毫秒,然后再往下小是微秒,微秒,再往下小是纳秒。

这应该都知道。

就是磁盘在磁盘中获取数据的时候,它是黄焖鸡很慢,然后但是在这个数据如果在内存里的话。

找到它,把它放到cpu计算,一定会很快就进了一个一个常识。

磁盘比内存慢了10万倍。

在选址上,慢了10万倍,大家注意啊,是寻址是寻址上。

是寻址上卖了10万倍,后边还会出一个小的知识点,然后内存的带宽。

内存里面数据来走,这个带宽一定会很高,就是它的带宽。

但凡多大我忘了,但是一定会很大很大。

因为内存就直接怼到我们这个cpu去计算啊,他有他直接走的那个数据的这个cpu的全能全能总线。

所以他无论怎么样,内存各种数据。

主要的内存里各种优势是优于我们磁盘的,然后还有一个小常识没有讲过的小常识。

还有一个小常识就是io 8分。

然后bug什么意思,我就用了一个buff,我就用了一个buff,首先其实这是一个成本问题。

什么叫成本问题,磁盘有扇区就知道和扇区迟到迟到。

和扇区。

那么一扇区啊。

一扇区多少字节,是不是512个字节,这应该是基础常识,这都是基础常识,那么这个时候注意有一个成本问题,是什么叫成本问题。

如果我们放了一个硬盘,这个硬件的时候都是最小力度。

以一个扇区,以一个512来找,那么一块硬盘是不是1t2 t是不是会有很多612,那么每一个512在哪呢,我的数据在哪一个512的那个里边放着呢,那么这样你要明白一个点,就是如果容器就是一个区域足够小。

那么它一定带来一个成本。

成本变大,什么成本变大,索引。

也就是你如果用,如果一个t里边都是512这么一个一个一个小格子,小格子,这样小格子的话,那么你上你上层操作系统当中就准备一个索引,这个索引就不是四个字节了,可能得八个字节或者很多个字节。

他一个能表示一个很很大的一个数字,一个区间才能锁定住这么多的512个这个小格子。

所以成本会变大,缩性变大,这个所以造造就了一个东西。

就是在我们格式化磁盘的时候,有一个4k对齐,对不对,是不是会有一个4k对齐,也就是真正使用硬件的时候,并不是按照512个字节为一次读写量,他会把这个变得更大一点,你读一个字节读512。

读1k他给到硬盘了,硬盘都咣当给你返回4k它是如果你看512跟4k就差了很大,它俩大小就不一样了,那么一个硬盘512很多小点点,4k可能有人会变少,那么这时候其实索引的体量大小就就就就会随着变化。

所以一般磁盘都是4k为这个默认我们格式化4k操作系统,操作系统吗,无论你。

读多少都是最少4k从磁盘的都是队长。

从从村拿这个这个这个事儿,这个知识点。

系列 3:P84:【Redis】数据存储发展进程 - 马士兵_马小雨 - BV1zh411H79h

哦数据可以存在文件里,然后数据如果存在文件里的话,如果我们要查询这个文件,比如说里边有马是兵,要怎么怎么怎么去查啊,一个文件里边有数据,比如说什么data。t i t可以怎么去查。

linux当中有grape,有a wk等等的这样的命令,你还可以用java语言等语言写个程序,然后做一个基于这个文件的i o流读取。

查找数据就放在文件里的话,然后你用相同命令去查的话,随着文件的变大,它就一定会查音速度变慢,对不对,是不是这么一个结论,随着文件变大,速度变慢,那么为什么为什么呀,是因为文件如果变大的话。

这时候访问硬件的时候,访问硬盘的时候会受到硬盘的瓶颈的影响,对不对,硬盘成为瓶颈,换言之,也就是io成为瓶颈,这是计算机目前不可逾越的,对不对好吧,这是第一个时间点,这是一个基础知识啊。

这个基础知识当中带出这些常识,那么随着时间的发展,如果数据都这么放的话,肯定节奏特别慢,如果能变快呢,数据库是不是出现了当时数据库出现出现的时候做了一件什么事情,注意数据库。

这就基本上2~3点可以去描述,第一有了一个data配置,这个配置真的它的低端配置的大小多大呢,是4k,现在如果再跟你说数据库里边,如果你有一张表,你建了一张表,表里面那么多行了,存档存到磁盘的时候。

他其实在你用物理存的时候,好像用了很多很多4k这样的一个小格子,那么这个4k刚好和谁一样,是不是刚好和我们硬件的这个磁盘子里边那个4k这样能对上,明白什么意思吧。

所以这时候如果我们的数据库准备很多这样的4k,也就是曾经数据是在一个文件里边线性,它虽然到底层的时候还4k,但是这一批文件混在了一起,这个4k连起来了,不能把他们割开,找不到他们在哪。

但是如果现在在在在我在我上面软件里边先定义出一个4k,然后每个4k有自己的id 0号1号2号,且这个4k啊,读取这个这个你要读这个4k这边某某一个某就要读它的时候。

正好符合你磁盘那个一一次的i o符合a4 l也没有浪费这个io,明白吧,你可以把它变得更小,比如变成变成1k,但是你会发现你你上层软件这个数据库想读1k的时候,硬盘是不是读4k,索性你还不如怎么样。

直接上面是4k,反正你你要查什么东西的时候,从我上面就掉某某一个某一个位置了,底层就咣当就把这个拿出来了,然后比较大可以比如我定义成8k 16 k可以定义小了会有浪费,定义大了无所谓。

定义大了是无所谓的吧,就是那个可以把大数调一点,但是调小的话其实浪费了,那你读1k底层还是都4k没必要,咳咳那么这样的话注意这是第一个知识点,它会分成很多小小格子,那么曾经这个文件里面可能1万行。

10万行就散了这么多的小格子里边,但是这个时候如果光有这个4k的那种小格子的话,其实你查找数据的数据的成本复杂度还是和前面一样,为什么,因为你还是要从第一个4k先读到内存,然后再读到内存,再多挨个去找。

所以他走的还是全量,i o跟前面io量是一样的,所以他一定会很慢,那么数据库怎么样可以让它变快,也就是建表,如果你使用数据库只是建表了,没有去建索引的话,其实那时候根本就任这个任何提速。

这个这个不可能出现的速度,一定的话会会会很慢,所以聚会的时候另外一个东西就是索引,索引其实也是使用的4k这种存储模型是对应模型,无非就是前面这个4k格子里边放的就是我一行一行的数据。

然后这里边4k里面放的就是什么呀,是我内行里边你面向某一个列,就是升证那一列,我就把身份证那列数据拿到这边4k里边,然后每一个生日号指向的是哪一个c的配置,有一个指向关系,这就是所谓的索引。

那么这个索引,所以你数据变大的话,那么你这个索引肯定也会很多,能看懂,同学们,这不能理解吧,唉就是一定要明白一个概念,数据是用4k4 k去存的,然后你的你的数据如果没有索引的话,速度会查。

查询速度还是很慢,如果想提升这个速度,你就必须有一套索引,搜索引系统,其实变相来说它也是一笔数据,然后这还有一个知识点,就是在我们建工业型数据库表的时候,在建表的时候就关键数据库一般是用什么尊重方式。

在见面的时候必须给出什么呀,必须给出,scheme,什么叫必须给成schemm,就必须给出这个表的啊,一共有多少个列,每个列它的类型是啥,就是约束是啥,那么这里边的每一个列的类型类型其实是什么呀。

字节宽度,比如我第一列是watch 20,那么这个第一列未来就是上线开开辟,就是他一定会开辟20个字节,那么当一个表为什么在使用之前要先给出sker,只要steam给出类型的给出之后。

那么这个表里边的每一行的数据的宽度就已经定死了,你懂什么意思吧,那么这样的话,未来如果你像这张表插入了一行,假设这一行有十个字段,有十个字段,你只给出第一个和第七个,剩下资本都没有给。

但是像这个data配置,你去放的时候,第一个和第七个以及其他那些没有知道那些字节都会就会用零去开辟,用空的东西去补充的那些字节,那么这样会有个什么好处,注意听啊,首先表里边这个概念。

然后存的时候更倾向于行级存储,就是以行为单位来存,为什么,如果你给出scammer了,给出宽度了,那么我这一行假设有十个字段,每个字都是四的话,就是40个,即便你只给了其中一个字段有值。

那么剩下的那个30多个我也会占空,把这一行位置站出来,就站位站位这样一个好处就是未来你的增删改,你比如在向其他补充的时候,你不用移动数据,直接拿你新的数据在那个位置浮写就可以了,也就是数据库。

关键数据库表示行情存储的,然后呢数据是数据,所以也是数据,但是这时候如果有了这个索引之后,其实还差一个东西,为什么你还要注意一点,就是数据和索引其实都是存储在硬盘当中的,都是存储的硬盘。

然后就是真正查的时候是要用到一个东西,就是在内存里边准备一个b加数,内存是速度最快的地方,所以在内存里边准备了一个b数,什么b加数,b加数,所有的叶子就是那些4k小格子,b加数,其实树干是在内存里的。

也就是说有的区间偏移,然后这个时候如果用户想查,只要命中索引了,那么这个查询在b加数会走树干,最终找到某一个叶子,比如你的身份证号,那个号刚好在那个叶子代表这个区间里,那么把它会读到从磁盘读到内存。

把它解析完之后,最最最笨的话便便列完了之后,可以知道应该下一次把哪个data配置放到放到内存里面读进来,那么就可以找到什么呀,找到我们那个那笔记录了最简单的b加数,如果复杂的话。

你就想二叉树中间如果是八的话,左边是小于八的,一边是大于八的,如果你要查查22的话,是不是一定走右边那条路,所以树干的话一定会沿着一个这个最小的方向去找,最终找到一个叶子。

叶子里边可能给定区间是比如说从那个930,那你221定出现出现在里边,但是930那些明细记录是在这个磁盘的那个小格子里的,你需要从磁盘读到内存,如果把这些索引在堆到内存里的话,你的内存不够。

存不下这些索引,所以索引和数据都放在磁盘内存里,只存一个树干,只存一些区间,就这么讲就可以了,这样的话是充分利用了各自的能力,磁盘能存很多东西,然后呢内存速度快。

然后呢用一种数据结构可以加快你的便利这个查找的速度,然后从而呢又数据就是分而治之的存储,所以这时候你获取数据速度极快,最终的目的是为了减少io的流量,磁盘有这么多缺点。

那么我就不让它发生大量的i o以及减少的水准的这个过程,明白了吧,哎那么这是我们的所谓的数据库这块应该很好理解,当这个理解之后注意,那么随着这个数据量的变大。

假设这张表这张表我不止这么几个data配置了,这张表本身涨到几千亿行,几万亿行啊,或者几百万行,数据量变大的时候变成1t2 t了,那么这时候你都应该听过这么这样的一句描述,就是数据库的表如果很大。

减脂速度一定会变低,也不是检索,就是这个性能一定会变低,对不对,那么这句话如果面试问题的话,应该怎么去打,就是如果16的表是不是好,很多性能就会就会降低,对不对,那么这句话在回答的时候你要小心了。

我把这个笔记能给你做下。

那么这句话描述的对不对。

首先增伤感,如果表有索引,如果不索引的话,然后增删改变慢,因为你要增删改数据,修改里面数据的话,这个数据你见了多少索引都会找这个索引列索引,你提数据去修改这个索引,调整它的位置,对没错。

就是维护索引会让你的增删增删增删改变慢,但是查询速度呢,查询速度会不会变慢吗,查询速度会不会变慢,增删改一定会明白,差距速度会不明白,那么这个时候你要两答,第一把有两个打法,这两个你都要出来。

第一个假设我这个表100个t硬盘就能装下100个t,然后内存也刚刚把书这个这个b柱的书干能都能存下,然后呢哪儿都没有溢出,那么这时候注意来了,一个人的一条简单sql查询其他vr条件能够命中索引。

那么这时候如果少量它就是一个或少量一个或少量查询依然很快,那六是什么意思吧,就是一个查询进来之后,因为你vr条件走的还是内存,b数走的还是一个索引块,这个孙块到到到内存依然走的是一个data的配置。

他并没有说你数据量变大,我未来会把别的位置也也要带到内存里面去,但是什么时候会查清流速度速度会变慢,也就是说当并发很多人到达了很多的查询都到达了,或者一个复杂的思路到达了。

那么这时候查询的时候不是要获取一个data的配置,当你存了有可能要获取,因为你数量变大,数据量越大,能够被很多查询命中的几率,被不同命中的几率就会很大,所以这个时候会受什么呀,并发大的时候会瘦。

刚才不是说了一个常识吗,也就是说硬盘的带宽对不对,手,硬盘带宽影响速度,也就是说假设来了1万个查询,每个查询查一个4k,就每个人查那边条件都不一样,刚好是用散弹不足4k上。

那么这1万个人查询东方进入到这条服务器服务器之后,那么这1万个人的每个4k是留着挨个的,像我们这个内存去走的,差一个你走差一个你走查一走,查你走。

那么这个时候其实有一部分就会等待前面那个4k他们走完之后,能轮轮到自己,能听懂什么意思吧,我刚才甲壳都是必数,不会受到影响,内存还可以,这块是咱能清楚同学的,就是这句话很重要,因为你一定要明白硬盘的慢。

除了寻址慢,是不是带宽。

是不是还有一个带宽,所以这两个你都要说出来,说你把哪个少说了,其实都是少覆盖了一个范围。

ok,好嘞,那么接着聊,那么数据库先简单聊了这么多分库分表啊,分制分布式这个事情不去描述它,那么如果说数据库已经使用磁盘了,那么这个时候其实尤其到后边这个查询,这也发现了,如果数据量特别大的时候。

它就一定会对增删改查,尤其在并发下的时候,他查的速度都会同等下降,都会变慢,那么这个时候如何去解决这个问题呢,那么首先看一个极端,也就是如果发展到最最最顶头的话,会一个极端。

这个极端是s a p这家公司有一个hanna数据库,这家公司有没有听说过这个汉娜数据库,有没有听说过这个sap hanna数据库是一个什么数据库啊,是一个内存级别的。

内存级别的关系型数据库行在这一个小常识啊。

这个故事我相信在哪都听说过,但是这有一个小常识,就是数据在内存和磁盘体积不一样啊,数据在磁盘和内存体积不一样,这句话能不能找到找找找找到那个点,什么叫数据在磁盘和内存体积不一样了,什么意思。

你要明白在磁盘当中是没有所谓的指针的概念的,数据是不可能出现什么呀,出现一个所谓像我们对象一样,我队里就一个对象,我可以不同的线程里边或不同的地方有不同的引用,如果数据想出现在索引。

那么比如身份证号就在这一定会出现,然后他就是原原原本,这还得有一个身份证号,所以这个数据一定会长出,一定会涨出,但是同等,如果关系数据库使用磁盘存存了2t数据,那么如果迁移到汉代的数据库的话。

当内存里边的不是2t,可能1t多一点,因为你这边不可能建一套缩影,而且它可以启动一些压缩优化的策略,好吧嗯好了,那么这个时候注意两个极端,有了这片有这么一个使用磁盘的数据库了,这边有一个基于内存了。

这边我们大家都买不起,这边呢我们数据量又会变大,然后性能又会变低,打半咋办,然后在企业架构当中,如果你现在给公司在维护着一个web一个架构,那么这个系统一定会越来越大。

里边的页面里边的数据一定会越来越多,然后这个时候如果这个东西你们公司肯定买不起,就甭想这个速度了,那么这边的话你肯定使用的是关于数据库,那么关于数据库,数据变大的时候,增删改查都会相应变慢。

尤其并发到这个这个这个出现的时候,所以这个时候什么概念出现了,那么有人说有没有折中,折中的方案,这个折中的方案就是什么缓存,这个过渡的这个过程有点稍显快,但是能知道我为什么要说这个缓存这个事了吧。

明白吗,就是说我还因为没有办法这个内存级的我买不起,然后呢,我还得使用磁盘机的,但是我磁盘记录特别慢,那么我就用小一点的内存把一些数据牵出来,放到这个位置,那么缓存的概念就被提出了,缓存里的记录有很多。

比如mitch,然后还有我们今天要讲的主角redis这样的技术好吧,这就是今天要讲的东西,就把它带出来,那么你就想成这个mac,这个redmc其实就是目前来说什么呀,目前来说没有办法。

所有的it信息系统都这么多年了,从194几年到现在,1966年还是4年,到现在4年应该是第一个这个计算机出现,有两个最基本的常识,两个基础设施,一个是冯,冯诺依曼体系的,硬件制约一个是什么呀,以太网。

和tcp ip的网络,这是所有目前的所有信息系统,两个最基本的基础设施,这两个基础设施没有办法,所以redis才能出现,如果现在硬件不是浮动,一般体系什么量子计算机出现了。

然后所有的硬盘io带宽的问题都解决了,那么估计就没有人再用redis,用mac开始做缓存这个事了,另外一个以太网tcp网络这种网络潜潜台词就是不稳定,所所以这个时候如果你曾经用一个技术。

现在要整合多个技术的时候,那么就一定会带来一些问题,数据一致,双写等等很多很多问题。

所以这时候后边知识讲的时候。

系列 3:P85:【Redis】数据库引擎介绍 - 马士兵_马小雨 - BV1zh411H79h

有这么一个网址是db的,就是引擎数据库引擎点com啊。

你现在可以随手在你身边,如果富余电脑,你可以看一眼啊,然后打开这个网站,上面有这么几个,一个是排名数据库引擎的排名,一个是数据库系统有哪些系统,每个系统它是干什么用的,以及什么特征,一个是相应的百科。

现在百科我们先来看一眼排名点他。

那么会得到一个很多的很多的数据库。

数据库里面有很多东西,首先你明白为什么讲它还是这句话,大家都是架构师,未来你都是架构师,无论你是你是真的架构还是摄像剧的,你都是架构师,架构师必须有一个能力,就是技术选型和这个技术的对比。

就是你一定要给公司做出一个正确的选型,你选对了记住选对了,咱就用这个数据库吧,就用这个了,那么你公司可能最后上市了啊,你选错了,一一堆人跟着你往下走,那么公司可能破产了,就这么一个最基本的一个概念。

架构师可以把一家公司带到上市,他有可能把一家公司带到破产。

这并不是跟你说笑,能理解吧,那么来看这个排名,在排名当中对我们数据库看第一名的是谁,是oracle,这是关于数据库,对不对,注意后边上的每行描述,它是一个relational的一个关系数据库。

第二名mysql,那么也是一个关于数据库第三名微软的sql server,然后等等巴拉巴拉ipad b two到第七名的时候也来试注意,这个时候这个mongo db是什么呀。

然后呢到原来sir的时候是搜索搜索引擎的,然后到第七名的时候,哎,release出现了,但是注意它是什么呀,它是k value型的,基于内存的,那么这个数据库的排位你可以往下多看一看,但在这要注意点啊。

他的排名是全部的排名,但是注意看左边是不是还有很多的分类,对不对,那么这里这里面关系数据库排名,你可以单看关系数据库的排名都是关系的,这里边一个会出现我们刚才说的s1 p的hanna,看了吧。

这个数据库也是有的,然后你可以再看kv的,kv的数据库,第一名是谁,是redis,这个对的啊,而且是基于内存的速度很快的,这时候你就知道为什么现在所有出去面试的时候,如果达到二三十万年薪以上了。

redis这个词汇一定会出现在什么呀,他那么一点点区域里边必须要写一些话描述的招什么人,但是大部分的企业bt等等都会把这几个字母放进去,就是他的地位很重要,别急,再往下走,这个网站有很多可以学的地方。

你先去把每个分类排名都去看一看,看看之后,其实这些分类如果因为咱们肯定还有一些小白。

然后从此之前没有怎么从事过这个这个这个这个行业的,除了排名,这个这个这个区域还有一个systems。

这里面会列出所有的,比如说我们拿两个最基本的好吧,后边这个关了啊,哪两个最基本的呃,拿一个今天要学的redis,然后再拿一个,我们好像是应该会用的什么呀,my circle,好像大家都应该会用的吧。

嗯那么找到架构师的感觉,这俩刚才给你演示了,一个是基于磁盘存储的关系数据库,一个是今天讲的redis内存就缓存,你先来看mysql的时候,它会给出很多的评价,这个这个很多维度的一个一个一个一个统计。

比如说官网,然后呢第1年什么时候,第一个稳定版,什么时间,当前的有点儿多少,然后开源开源否,然后等等的下边,然后这个operating system就操作系统,然后以及下边的ai,然后以及q的语言。

你可以分析出他有没有什么优势,如果你引起当中有一部分人使用某语言,但是这个这个这个数据已经不支持的话,可能就有风险了,或者你要不让你团队介绍他,要么是换另外一种引擎等的。

然后下边还有什么这种分布式的方式,可谓知分布式可谓之主从复制副本啊,主主复制主从复制是mysql可以支持的,他很多功能都可以支持事物是否支持一致性是什么,一致性是强一致性还是最终一致性。

你可以在这儿不用去搜任何的百度,在这块的可以拿到所有维度对对这个产品的描述,未来如果写标书或者和项目组开会的时候,就拿这个东西往往外释放输出就可以了。

而且除了这些往下,还有一些相关的评价和一些别人的那个东西可以去看。

那么除了它再来看release release一样,我们都说一下release release呢,它的网站是哪release dl,这是他的网站,走起后边可以关了啊,再来回来。

然后他的初始版本稳定版是09年,现在19年是五点的版本,五点版本,然后它下边是这个可以用的操作系统,然后呢最主要往下看sql与否是no circle,不支持sql语言的查询,也不是关型的。

因为它是kv型的,前边看到my sql的时候,买sl哪去了,这mysql的时候他sql为一定是一个circle能力吧,然后再往下看客户端言很多很多也就是它的生命力,其实我们的redis为什么火。

这点也很重要,因为它可以和很多的项目很多的源去集成,然后再往下还有它的分布式情况,集群集群集群模型是沙丁分片的啊,然后呢像mysql一般就是会做分桶啊,这边这个分库分表之类的,像redis的话。

后边给你讲到他的集群的时候,是一种上级分片,也就是把你公司的数据切成几个几个片,然后散在不同的节点里边,然后还有一个复制主动复制啊,然后再往下它的一致性,这块是一种最终一致性。

最终一致性并不是一个特别强的,因为其实使用redis的时候,你要做技术选型,对它的评价就是我为什么用它,就是因为它速度快,但是如果其他的维度去影响他速度快的话,那么这时候你可以降低不用它。

而用一个更强大更稳定的其他的引擎,所以这时候什么叫架构师,你不能破坏一个技术,它的特征,你破坏了它的特征的时候,其实它可能降级成别的别的别的产品了,能列吧,所以他这块他们自己的时候就没有使用强一致性。

而使用的是最终一致性,然后事物这块也是他自己组织的一个链式事物,然后in memory yes。

然后往下看,有一些描述,最最重要,往下看,有这么一段描述。

诶,这页面哪去了,我刷新一下,有一个东西得看一眼。

在这儿其实很多知识你都不用去刻意的去找,你看,看到这的时候有这么一个描述,redis in memory database,fast in memory database。

然后注意o p s每秒就是每秒的那个操作的数量是1。5m兆,那么这是多少次,每秒钟多少多少操作,mk是三个零,m是六个零,1x6个零是10万,对不对,不是150万,哥不是150还是15万。

接近每秒钟15万笔操作,那么15万其实说白了就是什么呀,毫秒级的啊,约等于小号小于号等级的操作,其实一般听到就是release可以达到什么呀,秒及10万操作这个东西,这个速度性能是远超过什么呀。

我们我们的观影数据库的关于中数据库的话,如果一般的话,它千级别就差不多了,千级别已经差不多了啊好吧。

你看就是你很多的知识都不需要老师,你只需要知道一些域名,你根本就看一看,出去面试的时候和别人聊的时候都都还ok,对不对。

系列 3:P86:【Redis】redis简单介绍 - 马士兵_马小雨 - BV1zh411H79h

那个听懂之后,然后最后来到他的官方主页。

公告主页呢是英文的,然后呢现在我们的市面上会有很多的关于中文的。

这是他英文的主页官方的,然后呢也会有国内会有很多中文的。

我那个英文水平其实不是特别高啊,所以这块儿你知道他在哪儿。

在哪儿去找他英文英文官方,然后多数看看这个中文就可以了,在中文这的话。

我们把这几个点拿一下,只能介绍他这个特征。

不需要老师的,但是需要我什么东西需要哪,以静制记载,当我把这些东西教教会你之后,本来你学新的技术的时候就变得容易了,这是它的一个官方的一个描述,redis是一个拉大一点,redis是一个开源的。

然后内存中的数据结构存储系统,它可以用作数据库缓存和消息中间件,然后这是前面第一句,第二句它支持多种的数据结构类型,它支持动手术一个类型,也就是如字符串等等,但是这要强调一点。

release的模型是它首先是建立对的,有k,有歪了,那么一定要在这儿注意redis里边的k和value才代表它是一个建制度,然后像这句话,它支持多种类型的数据结构,如字串这几个这几个类型啊。

说的是value的类型,也就是第一个它有一个所谓的spring,像建筑队这个非常好理解,因为你通过键可以找到这个value,这个value类型有spring类型,然后相应的还有一个,string。

然后哈希,类型的,然后还有list,最基本的是五大类型,然后后面混音每个类型给你讲,然后主要讲它的场景和如何使用,然后还有s,那么现在你其实要回忆了,回了你在做编程的时候,你离得开吗。

这些在在你做普通编程的时候,是不是也会用到数据,数据类型的概念和数据结构,对不对,因为程序等于算法加上数据结构,还有一个词汇就是这已经是够五个了,然后向下延伸出来的还有一个beat max。

这个知识点也很重要,它是完全用内存里边的二进制位来进入内存存储空间,但是可以解决很多重要的事情,然后string其实后面会给你讲,它既是ring,也就是可以用字符串操作字符类型。

然后也有整形整数类型操作或者数值类型,因为我写了bgmax,先把新版写出来,就是数值类型,然后等等其他的后边先不用写,有这么多,然后这是这句,然后待会总结redis内置了复制,然后落脚本。

llu这种驱逐事件就是过期等等的事物和不同级别的磁磁盘持久化,并通过redis哨兵和自动分区提供高,这个提供高可用性,就是可以他有集群class,然后也有一种主从复制的东西。

那么以上这里面先过多的先不说,过多的先不说,首先回到圆脸上,把它露出来之后,要去聊一个什么事情,在缓存,就是现在读完一个技术之后啊,你给他简单画一个像,画出项链之后,你就多类比,其实在这个世界上。

在这之前已经有一个技术,这个技术叫做mc,或者你不知道他啊,你不知道他,但是你应该能找到那种感觉,就是键值对的,他也是电子对的,kv的,都是kv的,那么ris是kv的,然后呢mac是kk的。

那么ready出来之后,反而还间接取代这个mad cat这个生存的地位,那么为什么为什么他会取取代这个mac pad呢,那么如果稍微一查资料,就会知道map当中它的value没有类型的概念。

value没有类型的概念,但是redis value具有类型的概念了,这是两个一个最本质的一个区别,你随便上网一搜就可以搜到这样一个结论,那么这时候你要正确的根据条件反射,你学过什么知识。

或者你活这么大的时候,如果看到这样的一个区别,你能给出怎样的一个结论,这就是知识,你要善于动脑,找到条件反射能力,什么意思吧,首先你要明白一点,如果就曾经我我在第一次学这个字的时候,我上了一搜raze。

说他歪了,有类型,然后我们开始没有类型,然后当时我大脑条件反射第一个东西是啥,这次跟着我的思路走啊,跟着我的思路走,为什么条件反射js那个东西,因为肯定开始没有redis。

那么如果假设世界上只有这种这个段,然后歪了没有类型,那么我们使用这个技术的时候,可不可以存一些复杂的东西,那么这时候你的条件反射是jason,对不对,jason它可以表示很复杂的的数据结构。

那么还有一句话,这是在我曾经第一次接触杰森的时候,我随便上搜资料,我忘了在什么地方有这么一句话,就是说世界上有三种数据表示,比如说等于a或者k等于一,然后这是第一种,或者是k等于123,或者是k等于。

然后ax f也就是上面这个等号,后边上边单元素或者线性元素或者是等于,然后一个x,然后等于y就是间段,或者你再可以整合出等于复杂的这种就应用,比如一个k等于一个数组,数组里边又是对象,没毛病吧。

这个你面试的时候都可以聊这个事情,为什么要聊他,其实这里面这就是为什么ready他这个类型会优于我们的map cat的,首先如果你条件反射想起这个知识,那么你会得出一个间接结论。

也就是说你value有没有类型无所谓,好像好像是不是无所谓,因为我mac只要有建筑对了,我的valley是不是也可以放一个js,然后来代表肯有有数组,这边你有list,我这边是也可以。

也可以用js表示一个list,你这边有有这种high side,就high table这种建筑对了,我这边是不是也可以放这个这个理论,能不能听明白,听懂同学来刷波一,好吧,当这个理论你明白之后。

也就是说其实我可以不用redis,我用mcash的,它的value也可以存很复杂的东西,但是但是注意了,你要再逆推一件事情,那么他们的成本,这个value的类型的意义是什么,因为你上面多了还有那个类型。

那么它的类型的意义在哪,如果注意听下面一个很重要的一句话描述,你就知道为什么你要学redis,如果我的客户端,客户端想通过一个缓存系统,而且是kv的缓存器系统当中取回取回这个value当中的取回。

value中的某一个元素,取个y6 当中的某一个因素,比如这个麦片当中y里面存了一个一个数组,然后呢你用原理当中的外表当中存在一个list,那么这时候如果想取回其中的这个它的js里边的某一个元素和直接。

如果它有类型这个例子某一个元素的话,那么成本就不一样了,那么相对mac car来说的话,mac怎么去做的,你需要返回所有的,返回value所有的数据到client端,那么慢慢开始台服务器。

如果很多人都这么都都这么获取的话,网卡那个io就是最大的瓶颈,而且这是第一个要反的客户端,第一个就是服务server网卡,卡l第二一个就是client端要有你实现的代码。

这个编码或者解码解码解码你的js把js劳动数据解码出来,也就是说只有两个复杂度,但是如果换成release的话,因为它有类型了,类型是什么意思,类型其实并不是太重要了,至于面试的,一定要跟面试官说。

类型其实不是很重要,重要的是什么,重要的是redis server,中对每种类型都有自己的方法,也就是说其实他可能给你提供了一个什么,基于index,让你给出一个索引下标或者l pop怎么样。

也就是你的客户端只需要向对方掉一个,我取那个vue的某一个元素,或者左边或者右边弹出一个元素,那么这个时候其实它就规避了上面的问题,你客户端不需要写很多的,因为它不需要把全量数据取走。

女主是server网卡就ok,然后你客户端的代码也比较轻盈,好吧,这个图为什么不管不管下扩展了,本质是解耦啊,那么在这个如果学过大数据的话,应该能给出一个词,这个词叫什么词,学过大数据的话。

应该可以给出一个词来描述这个过程,优势其实没计算向数据移动,计算是向数据移动的,因为你的客户端不是把数据拿回来,在这方面计算,而是说调查他的方法,你的计算方法是在里边发生的,数据直接回来了,好吧。

ok那么粗略的这么一个介绍,处理的一个介绍,从开始这个位置到到这个位置的一个演变的过程,先做一个简单介绍,一会计算向数据移动,没懂是什么意思,很好解释啊,memory catch。

你是不是要把数据你的计算在哪,在使用mac的时候,你的计算是在这个位置,这个阶段是什么,就是解析,js字符串,你的数据是不是一定会存在你的map cat里面那个value。

然后你的客户端是不是一定要盖的那个k,然后把这个外表是不是要通过他的网卡,然后是不是要回到你客户端,然后走那个计算,这计算对不对,公关雎鸠,然后但是如果是redis的话。

这个计算是不是redis当中针对这个y的类型是不是会有一个计算,然后这个阶段就在这等着,然后其实只等着你的调用了,如果你客户端说掉了一个一个计算,这个计算并给出不是某一个k对应的value。

那么这个计算就会在服务端发生的过程,然后发生完之后,计算的小量的结果会反馈给你。

磁盘固定4k大小,这是不一定的,磁盘其实有缓冲区啊,就是其实其实硬件都有缓冲,你硬盘上面会有一个缓冲区,也是基于芯片的,而且现在不止有缓冲了,就是固固态机械混合这种混合盘。

然后呢你的磁盘可以格式化成4k大小的一个格子,或者格式成更大了,为什么,因为取决于你上层应用访问数据的量,就是我掉你一次可能要多少,一般操作系统4k大小合适,不怎么浪费,然后呢也能支持你存一些小的文件。

小念不怎么太浪费,然后基本上中流入门就可以了,但是如果你你买了一个台服务器,想做视频录像,就你又买了几个摄像头,记得这台机上买了一个采集卡,那么这个时候其实你未来你想你把你写的数据。

和你监控上面播放的那些数据对磁盘的话就不是很小很小的访问了,那么这时候你磁盘4k其实就有点得偿失,因为寻址带来的时间这个碎片化太太太太大了,你磁头装照去的,还不如把4k变得更大一点。

让你的磁头飘到某一磁道上,直接读出更多的东西了,就减少磁头控制灯去寻址的时间,就把寻址再降低,也就是其实硬盘这个格子大小是4k呢还是更大呢,其实取决于你上层应用对于i o的这个使用量,就想怎么用它。

我是想更多的读它,就是io密集型的。

系列 3:P87:【Redis】redis安装实操 - 马士兵_马小雨 - BV1zh411H79h

首先要安装,要去做的话,我来介绍一下我这个环境啊,斯诺s这是一个linux操作系统,我用的是六点叉的版本,六点叉的版本,然后呢我们安装redis就直接从官网拿最近就可以了。

因为虽然版本变化可能从曾经的二点x四点四点差五点叉,其实里边最核心的东西变化不是特别赞啊,直接官网,那这些人。

这是个环境,然后呢我的计算机在上课之前已经重置了一台非常干净的,有人在你们实操的时候最好做一件事情,就随便拿了一台机器,然后呢给他拍了一个快照,然后拿了一个原始出装的那个状态给它转到。

然后拿到一个非常干净,那么现在我运行这个状态就是没有任何配置。

等于系统刚装完能有什么意思吧,得到这样一个系统非常干净。

什么都没有装过,然后根据刚才看你可以看中网,可以看英文网,它都提供了一个download,然后呢让你下载的是五点那个版本,把鼠标挪过去之后,看左下角那个状态提示,所以你直接复制复制链接地址啊。

在这儿做一个复制链接,然后可以给你粘过来啊,就是少去抄,然后能记住这个步骤和原理,你会发现这就是一个hp的一个一个一个资源的一个地址。

那么拿到它之后,可以在联想当中怎么去做,使用w get,然后后面接了个地址就可以把它下载下来,所以但是这个命令没有啊,因为是新系统干系统,你要装一下这个w盖这个命令,现在他先跟这个仓库同步一下。

这个稍微延迟一小会儿,等了一下,那你加目录,随便建一个目录啊,你是干净一点,cd到salt里,然后w get,然后把你刚才那个地址粘过来。

条条大路通罗马,并不是这种方法,并不是唯一的方法,所以你还在使用一些插p等等终端上传,无所谓的,咳咳咳,应该两边的这个两边学院的同学都有过记载,是不是看x f直接release解,因为它的源码体量很小。

其实他才1。9兆,他自己才1。9张,是源码嘛很小,然后剪完之后这个目录这是源码目录就能redis,那么这是一个常识,基本是源码,另行当中呢要按照程序都是c语言开发的,基本上都是c。

然后呢像源码安装的时候基本都是一个套路,什么套路,源码安装上来看的第一个东西叫做read me,你在github上面去访问那些java开发的代码的时候,他进去之后get up,任何项目看的也是read。

也是那个页面也是read me,就是无论你未来安装啥,就先看read me就可以了回车,然后你可以细读,也可以粗看,基本上他会告诉你这个redis的编译build在编译这个时候怎么去编译的。

他说is as simple,as就是make命令就可以了,执行make命令就可以编译,你还可以强调它编译成24 24这个32位或64位,还有test,还有清除make。

后边加第一次clean就可以清除你之前编译,如果编译出错的话,再往下找,除了编译过程,下面应该还有一些关于安装的,编译完其实好像可以直接使用,但是后边会教你就编译完之后run redis。

你直接在它的源码里面就可以找到那些编译完的可执行程序,就可以把它跑起来了,这是一种方式,还可以把它装到你的这个系统里,这是如何去使用它,启动它的客户端就可以使用,所以这时候其实根本就不需要老师。

然后installing redis,如果把它装到系统里面呢,是直接执行make install,或者是接上一个你想安装的位置,就修改的位置,因为它默认位置装在什么user local bin。

这个这个是它的默认的目录,你可以更改它的安装目录,就是在make install中间加上这么一个perfect的一个环境变量的定义,但是这个环境变量是随着这个命令执行,是有效命令,直接完这个环。

这个这个变量就失效了,还有一个install server。s h执行这个脚本,可以交互式的完成既有后端服务脚本,又配置文件等一系列的输出,完成这种服务器的安装,以上听不听得懂,但是你知道了。

要上来看read me,这句话,听同学来刷一波六,好吧,但是你要注意了,你你你们都是用过jav语言,对不对,嗯,java编译的时候是不可能缺少什么编译环境,就是编译器,对不对。

那么这个时候你看我们无非就做了,他让我们执行在这个目录下执行make,但在这多说一句啊,其实make的原理make是make后面的源码没有关系,make是编译命令,它是我们linux操作系统带的。

它是linux操作系带的,它是一个编译工具。

它不知道它需要跟随一个文件,叫做就必须找到一个文件,就是make f,你之前apex的时候是没有makefile,所以你要先执行confit,confit完了之后会生成makefile文件。

你可以回去再试一把,打开你index那个源码,然后它里边是没有make a fi,你所以你看他read me,他告诉你先进行confit,看完之后会有make file文件。

然后那么其实make命令直接如果回回车拍的话,他是要读这个make file,我们先简单看一下这个文件,make up make up,其实就是一个文件,一个编译脚本。

然后这里面会说了哎default or,然后什么还有一个title in star,然后里面会怎么做,如果你什么都不输出的话,就make后面什么参数都不带,那么走,他走的其实是啊,他要cd到src。

然后下边然后再去执行麦克病了以及代理的参数,如果你install的话,如果你make后面带in,刚才看安装的时候是不是可以make install,对对你make后面install并不是make命令的。

install,是你make a file文件里面这个title,你把它换成圈圈叉叉,那么你就你这安装的话,就是make军事圈就会触发这一行,这啥意思吧。

所以这时候其实你会发现这就这个这个源码跟梦下那个麦克风,make file文件就是一个跳板,它会跳到某一个目录下,然后那里边会真实的去执行你的每个命令,一代的参数,所以真身在哪,真身并不是他真身。

是在rc目录下,我们来看一眼v v i s r c可能会比别vi是cd cd的src的源码目录,这是我多讲一点,因为你们之前肯定是对零系统用的人不是特别多的问,然后在这里面你会找会有一个真身文件。

make a fire,然后这时候vi make file文件打开,这才是真正的一个文件,这里边写了很多了,所有的编译的环节细节怎么去编译,以及你可以杠这个斜线。

然后in store搜未来是不是他make后面可以带一个三角,in store那个引导会间接的从外面的make file让你掉到里边那个ssr c模下,int参数还会带过来,所以打开这个文件之后。

他也会找in star,所以找到in之后往下搜,唉找到音色开头这个开头,那么上面是编译的过程,下面就是安装的过程。

那么你看软件什么叫编译程序,安装编译就是拿着源码变成那些可循程序。

氨水的安装,其实就是一些什么拷贝的过程,拷贝过程,那么这里面会用到一个东西,就是有一个,找不到哪儿去了,有一个reinstall redis server name install b。

有一个perfect,来回忆一下,把这个推到文件上面,然后在这儿会找到一个特thanks,是不是在使用make命令的时候可以接install,是不是里边还可以再让你设置一个perfect。

然后这时候它你看它,它如果这个这个变量他没有找到的话,那默认user local如果找到找到你设置的话,那么就会使你设置那个能理解什么意思吧,然后给你演示一遍,就知道先把这个记住啊。

所以这个时候真正干活的回退,你还要回到这个源码,因为员工物件会有一个make f,他让我们执行mac,但是注意他还缺一个编辑器,但是我们他让我们怎么做,你就完全按照read me的流程去走。

他让我们怎么做,我们就怎么做走,然后这时候他一定会报错,cc command not found,cc是什么意思,c就是c语言的编译器,对不对,是不是c语言编系没有。

那么这时候条件反射基于linux的话,一般都装上了,是不是装g c c养in stop,因为我们的linux是格no linux,这个d是gal那个开组织的意思,能听懂吗,同学们能跟上吧。

你看我们装的是c z,而且使用样方式,它可以装很多的依赖,也该升级升级的东西,同意走,先把编译环境给它给它装起来,条理清晰吗,听得清楚吗,同学们,稍等一下把它装完,好了装完之后,因为你不是神。

你肯定不知道未来会发生什么事,但是你知道rise me让你干啥了,所以你就干啥,make还是只有make,而而而且这你要回刚才关掉的知识点,mac后边是不是任何参数都没带,任何没参数没带。

就是make里边那个default,就是他要跳进去执行那个编译的环节,所以make命令如果一般来说通俗来说make直接执行,就是拿着make fa去做编译,回车就是又报错了,就报了一个啥错误。

你犯depend,我们来切一下make dc t,这次cream,因为刚才执行一次编译时报错了,所以你要清一下刚才那个编译编译报错了,您您您临时文件,而且这个命令并不是我从哪学来的。

是不是read me里给我们提供的,比如你编译刚才是不是你只要通读一遍,read me里边是不是告诉你了,有那么一个make,然后this is clean,没毛病吧,所以我也不是神,对不对。

有笔记后面都是,我想你带带那个流场现各种思路走,然后我待会把笔记给你写到图上去啊,好了装完了,他说it's a good idea to run make test,可以做一下测试。

但是一般我们都比较懒,这不就就不去做了,因为它的消耗时间太多,但是到公司的时候,你肯定是要编译的时候测一下,看哪是不是编译,有有有这个有bug漏洞等等问题,好吧,那么轻松,刚才做了什么事情了。

是不是就执行一个mac缺什么补什么,确定资金补贴资金,然后执行mac的时候出错的时候该清清清完,找make之后成功了,make完注意分解一段,make完之后去你的sr c目录下就有了一些可执行程序了。

比如redis的server和reci client就有了,那么一般你在这,比如说在这个目录下,我就可以redis,然后server让它跑起来了,回车它就一定能跑起来。

明白吧,但是这个时候其实你到公司的时候,你的软件的启动不可能每次都人工干预。

这种方式是不是特别low,对不对,所以这时候你肯定是期望把redis这个程序的一个进程ctrl c给他,ctrl c可以给它结束掉,那么你期望的是让这个程序它更像一个服务软件,就曾经装了一个服务。

然后变成一个服务,但是你怎么去构建呢,ok,刚才在read里面也看到了,util是目录下或一个脚本叫做in all server,明白了吧,这些东西都不是我跟别人学的,就跟着read me。

来来来来来来学的,所以这时候你就直接按照这个insl来做就可以了,但是毕竟我装过,我告诉你一个前置条件啊,来吧,少做一少少,少做一步少做,先先要去装,因为再带你看一遍,看一遍吧,read me。

然后找到install,咱们先按照流程走,也就是上边如果你编译完make编译完之后,然后你可以在它源码目录当中cd s3 c跑server,然后跑client可以来使用。

但是你更期望的是把这个程序install你的那个操作系统里去,所以我们有可能要执行make install或者make带着perfect install就装到某一个目录下,这个装完之后软件安装进去了。

但是你更期望的是把它变成service,所以在执行一到server就走这么几个流程,这些流程都是从我手机里来来来来来得到的,能理解吧,所以按这个流程走,第一个是先去安装make。

然后你要装的是install,安装安装哪去呢,你可以接一个perfect,然后告诉他装到o p t,然后b啊,咱们叫什么呢,马士兵吧,马士兵,然后下面有一个redis 5这个目录,这能看懂吗。

make install这个造是不是make sc目录下的,造里面是不是会执行安装的过程,profix是覆盖它那个脚本,那个脚本文件里边那个那个那个变量告诉他一定要装到这个木下,然后回车。

然后这时候你去看o p t,然后马士兵,然后这个木下他就会帮你创建redis,然后去到redis目录下,然后会有一个bin去到b目录下,你就可以看到深那个刚才编译完那个可执行程序。

帮你牵出了签到你系统的一个你的安装部定下了,就没有和源码混在一起,这部看懂的同学来刷一波,一你看懂了这部在干什么事情,好吧,但是这时候你要注意啊,我只是把可执行程序这个文件放到了系统的。

我希望安装这个路径下,但是这时候想执行的话,依然还是这个梦想,我要执行的redis server,让它好起来,但我更期望的是使用曾经那种比如说什么server,然后redis,然后star把它跑起来。

但是现在都不支持,所以还缺了一步,把它变成服务,那么别的服务怎么去做,然后回忆这个read me文件里边是不是让你证据做的来到源码目录当中,一个intel server,就把它安装成一个服务。

安装一个一个一个一个server,那么执行它的时候注意这个隐匿的那些东西都不允许手工做,执行它就可以了,但是这个脚本未来他需要知道你的程序安装在哪个目录了,我们要多做一件事情。

v i e t c级的profile文件到文件,最后新开一行export,定义一个redis home,一般我们在操作练三组当中装了什么什么什么程序了,是不是都要把它home。

然后及以及它的bm可执行程序文件追加到pass那个环境变量里,你追加进去了,你就可以在任何位置使用那些可执行程序,这是一个基本常识吧,你扎了是不是装完之后也得十加home。

目标不是为了设置扎后面是要为扎后面接的那个b接到pass里去,所以你的所有你的扎入命令在这个位置可以执行,所以我们在这来做是o p t,release,先把它的安装路径加进来,然后exp。

然后是大写的pass里边等于dollar把pass拿出来,再拼上我们的redis,home下载b目录,主要是要接这个ban ban里边有那个reserve和replan,然后把它加完之后保存。

保存完之后注意配置文件是死的,它存在磁盘当中,内存里面做程序只能跟你配置吗,不知道,所以south etc profile文件。

然后这个时候echo dollar pass里面就会出现你redis那个闭目录了,所以你可以在任何位置,起码说我可以直接redis ci就可以起客户端了,这个位置在任何位置可以用了,这个听这个环节。

听同学再说一波一,这是一个常识吧,对不对,这是一个小小常识,当你有了这个之后,你再来调这个install server,它就可以通过上面这个目录里面找那个命令,就知道你的安装路径在哪了。

这是他需要这么一个过程,如果你不是的话,请你到时候手敲也可以,我们来走一遍,下一个流程就是在当前目录下执行install server,注意看回车。

这时候please select the redis part,端口号for this issu,也就是我们希望在我的联系当中安装一个ready的服务,但是他告诉你必须选一个端口号。

这个逗号是你当年实力的这句话,另外一个意思就是一个物理机上边可以跑一个redis,也可以跑多个release,他们靠什么区分啊,靠什么区分,是不是靠的是端口号来区分,对不对,那么这时候注意它。

括号叫做默认选项,你不填东西,后边等你输,你不填东西,它默认就用6379,而且得出一个基本常识,如release默认东口号是6379,如果不选,就按照6379,因为这是目前的第一个实例回车。

他会继续追问你,please select什么呀,release confish f配置文件程序都是有配置文件的,注意它放到哪去了,a d c是不是放配置的目录,他在里面会准备一个release目录。

且为你这个实力准备一个为你准备的6379点康复,也就是如果这台服务器这个脚本我吊起十次,我可以装十个in,30个实例,十个端口号,那么每一个实例它的配置文件的名字都是随着端口号而变化,不会覆盖这个。

再听我同学来刷一波一,也能跟也能跟上的对,然后再看除了配置文件,程序运行的时候是不是还需要日志文件,日志文件放它帮你规划到war war是不是放数据目录的,放数据的目录,对不对。

所有的日子都放这个目录目录就放,然后里面会准备log redis,然后加上端口号的日志,然后只要你上面给个断号,所有的资源文件都能通过端口号来区分和隔离,对不对,然后我们再走,默认再走,下周会告诉你。

slides data directory就是数据目录,那么这问一句,redis不是内存数据库吗,他为什么会有一个磁盘目录来存数据呢,因为只要提到内存的软件,它都必须触发一个技能叫持久化。

因为内存掉电一失,对不对,那么注意你看这个目录是不是又是拿着盾了号去区分的,也是6379,所以你装了很多的实力是不受影响的,reecutable就可执行程序的路径。

那么在这儿他怎么知道是装在这个目录下了,是不是我刚才那个环境变量的配置,如果环境变量没配,你是不是在这儿手敲这个命令的路径,这也能听懂吧,所以我配了它自动识别到这个位置了。

那么好好就是这个位置,回车上面一系列选择完之后。

因为第一个我就不去改,待会再装备,我再去改它,然后这时候告诉你这个sley,你选择的配置如下,顿号6379,巴拉巴拉拉,然后这时候如果你觉得ok没有问题的话,然后press enter回车。

然后要么ctrc结束了,流程什么事都没发生,我们现在就回车,注意看回车之后啊,注意看,回车之后回车拷贝他在临时目录当中书写了个六分七,有点看,我把你前面很多的东西都写到这个配置文件里去了。

然后并根据上面的描述放在这个目录下,这是第一件事情,第二事情,installing service安装服务,他其实是把什么把一个启动脚本装到哪去了,装到了e t c的引擎的木下。

bkill confide做了开机启动,在二在35启动b他还帮你把redis提起来了,那么这是常识,注意听啊,这是常识,他能做to confish,能做开e级服务启动的话,他一定会向哪个目录。

是不是cd etc init。d的一个目录下,他一定放了一个东西,就是redis 6379这么一个脚本,注意这是一个脚本,这个脚本当中他书写的,你看我们的可执行程序,就是刚才他识别那个程序。

然后它的配置文件就是他刚才形成配置文件,只能看同学来稍微一,那么有了这个脚本了,并可执行了,带绿色了,是redis,然后start吗,或者dies吗,一定要写这个脚本的名称,才能是这个脚本名称。

就是这service这个后面接这个东西,对不对,所以后面接着下划线6379,然后可以statues来看一眼,rice is running,在6244这个竞争竞赛,为什么呀,因为你上面安装完之后。

是不是他给你做了一个starling,服饰已经跑起来了,以上流程整体看明白的同学来刷一波六,好吧,你能装一个实例,今天是不是可以装多个实例,你再回到这个目录下,去哪儿,注意这个时候要注意我的程序磁盘。

那个可执行程序是不是装在那个o t0 目录一份,对不对,但是这时候未来我这个计算机的内存里是不是可以release的,几个进几个实例,程序文件是不是只需要一份,那么内存里的时候会出现他多个进程的呗。

一来自这个肯定程有多个进程,多个进程他们是不是来自于不同的配置文件,未来使用不同的持久化目录,对不对,也就是程序是一个涉及的资源和内存是多个副本对吧,那么这时候我们还执行这个脚本。

install server回车,那么这时候他走的肯定是脚本里默认值,那么639我是不是中国了,我只要告诉他6380,给第二个实例,然后回车,然后这个数你看以下的配置目录,所有文件是不是都使用6380。

对不对,都能区分出来,你根本就不用管,然后但是程序是不是来自于一份程序一个版本的,然后再来回车,是不是告诉你1380,你觉得有问题吗,没问题回车,然后这时候会告诉你怎么样。

又是你这个这个安装完了并给你启动了,所以那时候sorry,redis 63804364是不是又一个跑起来了,然后这时候你可以用什么去验证,ps杠f e grape redis。

这里面redis是不是一个一个进程,646244,刚才那个一个6288,这两个进程是不是使用了不同的端口号,跑在了不同的,但是程序是来自这个同一幕下,同一个程序在内存里边,是不是他使用了不同端号。

系列 3:P88:【Redis】redis安装实操总结 - 马士兵_马小雨 - BV1zh411H79h

好了,讲一遍写一遍,做遍笔记,回来趁热打铁,别忘了静静地回忆一遍,安装的流程和步骤是什么,把它背一遍,这样记得更清楚一些,关关说跟其他讲的是不一样,你看过谁的呀,第一步要什么,要准备一件什么事情。

我给你写完整吧,是不是在你心目当中要em install w get这个命令,优秀有一个版本也是我讲的,懂了吧,当然后面的版本不知道谁讲的了,来先不讨论这个事,咱们接着来啊,接着来,第一步是要装wg。

有这个命令之后,你可以下载这个源源码,对不对啊,然后cd到你的家目录,然后呢第三步make dr创建一个salt目录,然后第四步cd到salt目录下,进去之后第五部是w get。

然后那个地址是来自于上面那个地址,我写啊,你得跟着跟着一块回忆好吧,我给你放大点,这个字应该有人看不清楚,这样清楚一点吧,再大一点,咳咳咳,第六步有了它之后。

然后tx f有人说你为什么不加v,别人是不是写了好长啊,带一个中线的位置,中间带不带无所谓,是不是还带着v,然后这时候有一个小常识,就是你要明白啊,我们你在公司当中拿的是客户端。

这是一个插上windows一个东西。

你带着v它抵押的过程,所有细节会通过网线回想到你的客户端,会对你台服务器造来造造成一些io的影响,对不对,所以其实你越搞得深的人,其实更期望什么呀,io上规避一下就可以了,所以我把那v我不我不看了。

反正要么成功,要么失败,直接就是xl 4轨的解压这个文件就可以了,没错,倒数gb o,然后把它解压完之后,然后你要c到源码目录,我就用别名了,你c了他那个源码模式之后,然后第八步很重要,看什么。

任何的源码中都看什么,没错,你只要把这个学会了,未来你装啥都不怕,你现在可以,今天晚上可以回去之后再装一遍index,你读一遍他的read me之后,你再来,你再来看看它是一个什么流程,对不对。

看完之后,然后呢你肯定跟着他的流程走执行,make直接max的时候一定缺失一个什么东西,你要安装install一个gcc,然后肯定是还得去需要什么呀,make,清楚一下,会有这么三步缺失,这么几个缺失。

就是你可能像mac了,mac已经产生一些变异的东西了,垃圾了,然后报错了,然后你补全报告你缺了缺了cc,然后你就安装这cc,但那些垃圾已经产生了,然后你如果在这种mac main会报错。

所以说要先清一下,切完之后,然后第十最终在执行ma,mac执行完之后,你会发现去他的src目录下,然后里边儿就已经生成生成什么了,生成了可执行程序,然后但是我们更期望的是,未来把它变成服务化。

服务化之后,你需要在这个它的源码目录,这是刚才cd了,你再退回来,看完之后再退回来,退回来之后,然后再执行一个make,然后in store,但是给了一个环境变量,给他那个脚本pr等于,然后o p t。

然后是马士兵,然后redis 5 rudy美女随便给这个目录没有,无所谓,他会帮你创建好吧,然后这个时候执行完之后,你去检查那个路就有了,然后这时候多做一件事情。

v i e t c写的profile文件,然后15步啊,这个打开文件之后在里面写什么东西,要export,然后一个rid home,等于你刚才那个o p t马士兵redis 5,没毛病吧,然后再。

在下面再写一个,pd pass等于dollar pass,拼上一个dollar redis home,你主要要的那个闭目录,可是程序那个位置,然后这步做完之后保存15步,当地延迟做完之后。

cd它源码的you tel目录下,然后在这里面16步。

然后触发它当前目录下执行install server。s h,我看见那个中线是中线,是下划线啊,下划线是一个下划线,执行执行的过程当中,有几个东西,有几个知识点,也就是第一个知识点,什么知识点。

一个物理机,一个物理机中可以有,多个redis实力就是进程的意思,我做个ready进程,通过part区分,因为他们要通信嘛,通信的时候肯定需要有,各自有各自的这个动口号,然后第二一个。

然后这个程序可执行程序就一份在目录,就上面这个目录下来放着啊,但是内存,中未来的多个实例,需要各自的配置文件和持久化,持久化目录,等资源就是这个流程当中,你要给出不同的段位号。

它自动的会帮你完成不同目录,不同的配置文件的一个初始,对不对,听理解了吧啊啊,刚才少做一个sce,在这加吧,一个sse s o u r c e,然后a d c的这步你要不做的话,他是发现不了的啊。

然后再到它安装,它能跟着吧,是不是这么一个流程,然后这样完成之后,然后其实最后你会发现他还给你,给你做了一件事情,就是一个最基本的一个常识,这个常识就是service。

后面接的是redis gone 6379,然后start stop或者studi,或者是638063666381,这个东这个东西会变,对不对,然后它的知识常识来自于linux,用的是etc的it。d。

下面会有这个脚本清新星,这样清新星这一个脚本,这个脚本也是通过它来实现,给你部署进去的,而且绑定那个段位号,我就做一个简单的一个笔记了,回去你可以拿着图之后,可以自己在网上写的更细一点,可以吗,同学们。

好吧,当执行完之后,然后下一步他还会帮你启动,脚本还会帮你启动,ok搞定,你可以装这个这个脚本,可以执行一次或多次,对他帮你做了七个confide啊,他帮你做了cheer confide啊。

好了,你只要按照这个做,就一定能把它装成功,看着a边线降成一个将近一点好吧。

ok,那么好方向来说。

现在我已经装完了啊,对验证这个命令你可以再加一下,你可以做这么一件事情,是p杠f e管道grape,redis可以看到是不是会有多个进程,p和e grape,然后rise是不是两个今天就跑起来了。

为啥要装到linux系统下,是只能安装在linux系统中的,不是windows也可以装,问那能装,但是我们基本上服务都是跑在linux的,我不make直接安装这cc,然后去make是不是就不用清除了。

如果你直接安装gcc,就不需要做那个清除,因为你没有mac就不会产生这个垃圾,对不对,脚本是自动做了开机启动吗,是啊,你看上面直接脚本之后,我看到你看读啊,你一定要注意细节,好多。

我带过这么多年的学生了,其实大家都有一个通病,就是你在盯着执行命令之后,你就一闭眼,我看不见看不见看不见,但是人家真的说了,人家说了啥了,拷贝这个东西过去了,然后安装服务,安装服务。

其实就是在向那个e d c。d模下,拷贝那个脚本,然后并执行了什么呀,这个config,然后它运行器是345的级别,就是命令行和图形界面都会默认开机启动,然后并且还把服务给你start起来了。

就等于执行了service rex 6379 start,然后比如告诉你诶成功了,所以这时候你直接看这些提示,都能知道他在干什么,make是干啥呢,make是一个编译工具,make是编译工具。

make加上make file文件,make缺失的mac文件,他是不知道应该先编辑什么,后边什么的,make file文件是你的源码的厂商,给你提供出来的,妹妹只是个工具。

就跟你那个java c这个命令一样,但是编译啥你后面得给出参数的,对不对,或者n t编译这样的一种工具的。

哼没错,就是类似于加了新的命令,好吧,你这么理解就可以了,但是他不是只面向一类语言的。

系列 3:P89:【Redis】epoll介绍 - 马士兵_马小雨 - BV1zh411H79h

潘总啥是一炮,刹车一炮这块要从这讲吧,我这么讲就有点有有有有有点累,我简单跟你说一下吧,公开课有人听,有人没听过,是不是不是,我现在简简单说一下,咳咳咳,计算机啊,在这插一个小小插曲。

做一个查询计算机使用内核,内核呢像内核可以接得住很多的连接,然后向下是有连接的,是有所谓的客户端,我觉得直接下边就是扣端连接,有很多的客户端连接,然后客端连接肯定有很多,然后所有的连接肯定是先到达内核。

对不对,新内核,然后这个时候早先的我们的内核里边会有这个连接,其实是文件标符,然后呢早先是通过瑞的命令,一个连接就是一个sd文件描述符,比如文件描述符八,然后这个是文件描述符九。

然后这里面这个瑞兹说我要读一下八,我要读下八这个文件标符,那么这是你的一个线程,你可以有一个县城或者一个进程线程,或者是因为栅格路我们肯定是线程,然后另当中就是进程,它就是fox的。

但是n n x就是使用的什么呀,一种异不飞蛾的,但是现在描述是早先的,那么这个时候他肯定是期望的什么呀,是瑞的,md 9我加这个差距可以吧,朋友们加这个差距,因为的确是要讲他这个模型啊。

这会儿讲他还是靠谱的,那么这样的话为什么,因为read,因为socket在这个时期,是block blocking是阻塞的,socket是阻塞的,也就是socket产生的这些文件描述符,你读它的时候。

你这个月的命令就不能返回,就在那阻塞着,所以是blocking的,那么这时候之前我们的早期的7。01版本之前的ti是阻塞的i o,也就是说你需要抛出一个线程,然后读这个网网卡。

这个连接有数据就就处理没数据,在这阻阻塞着下面那边执行不了,你只能抛出更多的线程,抛出更多性能的话,如果你只有一颗cpu的话,其实某一时间片上面某一个时间点上只能有一个线程处理,这里面数据还没到。

但是别人数据到他还不能还轮不到他处理,所以整个的计算机其实cpu并没有时刻在处理那些真正到达的数据,会有很多资源浪费,以及线程,更多的话,切换线程是有成本的,所以这就是早期的bl时期。

因为socket是阻塞的,所以叫bl,好吧,这是第一个时期,那么这样的话,计算机硬件是很难被利用起来的,所以谁发生了变化,内核发生了变化,注意再来画一张图,内核肯定是有一个跃迁,一个变化的过程。

什么叫就一个月迁一个变化的过程,在联系当中都可以看到这个东西啊。

首先我们可以通过em install一个man帮助man,然后gpages manu是看帮助的一个帮助程序,my page,所有帮助e回车。

把这给你补一下,你要想怎么去做,先用这个知识,ym install men和menu pages。

首先把刚才的知识理论验证一下,menu可以看,比如我们之前用的命令,比如说ios这个命令怎么去帮助的,它是一类文档,它有八类文档,帮助程序可以看八种类型的文档,然后二类是系统调用。

就是内核可以对外提供,像那个re的命令。

就是一个系统调用,然后比如说can read回车,然后它是二类的信标用啊,就是内核给我们程序暴露了一个调用的方法,对吧,然后这个apple是一个总称。

它它系统调用有一共有三个e create eo cd l e le weight,先来看这个早先的那么吊瑞的时候,这个方法里面传的是不是传了一个文件描述符,文件描述符就是file descriptor。

java当中是用object来代表一个对象,代表一个输入输出流,就是input output 10秒,在linux当中它不是面向对象的,它是一切接文件,所以都是拿着文件描述符文件来代表,这就是一个数值。

1234讲成立项的时候,应该都知道零是标准输入,一是标准输出,二是错误输出,然后你再开启这个这个新的这个这个i o的话,就会产生更多的,比如说我们可以看一眼啊,克隆一下这个标签儿。

任何进程在操作系统里面都会有他自己的i o对应那个文件名符,ps杠f杠grape redis,然后就看6244这个进程,然后怎么去看c d p r o c6244 ,有多少个o呢。

一切皆文件在你联系当中都能看到程序里边的那些东西回车,且这个redis有动用了pap的调用和一炮,even the pp,这就是一pl有socket,因为它开启了一个63791个逗号。

这是所谓的文件描述符,这个10123456就是文件描述符,任何的进程都有,那么有012就是任何进程,这012肯定都有的,剩下的是v其他的好吧,那么回来看先知道你re的是内核。

内核暴露内核爆了一个read,然后他能读一下描述符,那么关键这个描述符对应那个socket也好,对应的那个连接那个文件也好,它是一个什么什么什么什么形式的,然后再来看。

man 2 socket学dio的时候,我们是不是可以用server socket socket来开启连接,对不对,所以链接对不对,那么这个时候你注意看引力了,你要掉sy的话,然后也给出毒慢预瞄。

然后这时候看如果你要所有的看下边,这里边会有一个隐秘的tab pro,就是八零啊或者22这个协议,前面就是那个主主这个地址,然后int tab这个tab是什么意思,往下往下走。

就是调那个socket方法的时候,给你返回一个文件描述符,文件描述符是什么类型的呢,这个tab什么类型的呢,往下走。

再往下下面这做的tag。

然后如果你传了一个socket nblock,number什么意思,nblock什么意思,是不是飞蛾啊,哎那么这时候并不是给你瞎忽悠啊,就是socket内核当中socket可以是非阻塞的。

所以才有了一个非阻塞的,就是你一定要明白,io好像看似bo ni o和ao 3,但是它的发展过程是很细节有很多的,首先是因为内容的socket可以是nblock,刚才是不是一定是blocking。

也就是其实对应的文件描述符是nblock,这个文件描述是不是可以nblock了,那么nblock之后,这个时候刚才说了,线程多是不是会有弊端,那么这时候诶你不阻塞了,我是不是可以用一个线程。

比如说就用一个县城,我就一个cpu,那我就让这一颗cpu上面只跑了一个县城,只跑了一个进程,它不切换就尽量少切换那一个没用的,然后这个线程里面写一个循环死循环,while死循环先去问read。

然后文件名八,哎你给我给我给我给我读一下,然后他肯定给你返回什么呀,告诉你有数据或者没有数据,然后这时候你变了八,发现没有数据好,你再编列谁啊,然后f d9 ,没什么意思吧,就你一个进程可以循环先掉。

先先先去读他给你返回没有,那么你就再去读它哎,给稿里有了哪儿,有的东西可以开始处理,处理完之后才能再去循环遍历文件图标,文件符里面名符吧,它没有,然后再进来往下循环,一直循环便利。

就是轮询明白这个轮询发在哪了,轮询发生在了用用户,您,能听懂吧,这个时期叫什么,这个时期就是非阻塞io的到到到哪了,但是它是同步还是异步的,什么叫同步,什么叫异步,什么叫同步啊,什么叫衣服便利。

取出来处理都由他自己来完成,所以叫同步,非阻塞时期,是不是不堵车,是不是堵,你一下就可以记完做代码,但是这个所有你有的时候我我从你取出去的事,是不是还得自己做,是不是同步fix 11,这这这能听懂了吧。

然后这个时候就可以叫什么,是不是可以叫n io了,很清晰吧,但是技术是永远向前发展的,但是技术的发展不是因为技术,而技术就是你非要酷炫,技术一定是要解决问题,那么请问我现在的问题是什么。

我请问现在的问题是什么,这个模型已经是同步非紫色nl了,那么问题在哪呢,问题在,问题在哪,还没有到钩子呢,因为先要再出现一个多路复用,后面才能是什么呀,才能试这种就所谓的a l异步的,代表用户进程。

轮询调用1000次,就是成本问题,注意这叫成本问题了,是不是成本很大,因为想找到问题问题才能促使科技的进步,也就是这个进程不是自己处理不处理的问题啊,你写那个后边的多路复用也是也是自己做这件事情。

他是自己的一个用空间查询一个文件描述符,就得调一次系统调用,然后内核用态内核态切换,cpu保护现场恢复现场一大堆,是在那换来换去,换来换去,这是随着你的这个连接数,如果其实连接数很少的话,无所谓。

两三个两三个连接7度也也也就这样了,没必要往前发展,那么怎么解决这个问题,当你发问题的时候,怎么解决问题,如果有1000个,但是这1000个里边谁能不能读了。

不需要触发1000次性掉一次掉两次就能发现这个问题,是不是可以加快这个速度,就是将这个问题不解决就可以了,但是要想解决这个问题,少减少这个这个这个性教用,那么用户自个儿能实现吗,是不是实现不了。

所以内核得向前发展,能跟着这个思路吧,就是内核不变,这辈子你可能实现不了,没错,就是把你这轮询的事扔到内核里去,内核里从而多了一个系统调用,他就是增加一个系统,这个系统要用早期叫什么呀。

叫做select,来增加了这么一个系统调用select,然后这个时候其实你的用户间是调那个新的星标,用了新的调用的时候,其实就是掉个select的一个系统要用select。

但是掉它的时候我们可以看一眼啊,如果你的进程想掉select吧。

下边假设1000个文件名符进来了,来看推出来menu 2 select性调用select,然后这个时候注意看这个时代方法,然后int然后number有多少个文件描述符。

然后这需要一个指针指向一个没有符的一个结构,这里面是你要想读的那个一共有1000个文件面符,然后sd有有就读写了两个方向的,你要把1000分都作为参数传给了个系统要用,然后有没有报错,就这么三类啊。

以及这个这个轮询时间是立刻还是阻塞在这个这个轮询结果上,这是掉了一些疗用,那么这个sli可以完成什么事情,就是内核里边提供一个slide,然后select就完成这件事情,你看这个字根本就不需要老师。

完全你你看看看看人家的帮助就知道了,这是同意a program,一个程序to monitor,监控更多的failty rever,文件描述符是个负数,然后waiting until,等待直到什么呀。

直到one or more,一个或多个of the fidistributor,文件描述符become什么呀,reading就可以触发io操作,这英文读的还行吧,还可以吧,啥意思啥意思啊。

画一下画图是这个世界上表示知识,表示原人类沟通最重要一件事情,比如吊带的时候要穿啥了,曾经建了一个一个连接,你这边拿到了他一个文件描符,以前是自己用写一个死循环,现在不写死循环了。

哎我统一的把这1000个文件描书传给你。

然后你去做一件事,什么事情,你内核去什么呀,这个监控这些东西,然后waiting until one or more。

文件描述准备好之后,并且return返回,返回之后,然后他再返回之后,你再拿着返回的那个文件描述符,水有了,然后再去调什么叫read,如果还有一个性能用,就再去调这个read。

我就把rate不会调那些没有数据的那个文件名,read,是你在这步完成之后,是第一步,第二步,第三步可以返回之后,你拿着的反思结果编译一遍,哎,你因为你给他传1000个,他可以给你返回1000个。

你的1000个便利的1000个哎,在这个里边看一眼谁谁谁那个状态标成那个有了,然后直接掉瑞的,然后把那个文件没传进去,给他传,三传的是有数据的那个文件名符,那么这样的话这个时期和前面那个时期一对比。

你会发现多了一个什么好处,精确了,这两个时期比较是不是内核的发展,觉得这件事情让你用空间复杂度是不是变低了,啊这是应该f d s严谨一点,这是一个复数对吧,能看懂吧,哎没错,批量批量交给别人去轮询啊。

你给我的时候,我不这个主要不是轮询多少的问题,是不以前1000个,我说掉你1000次,现在1000个掉你一次,我等着你回来告诉我这里边50个,那我就得50个挨个挨个去读,它还是这个同步非阻塞的。

这只是减减少了这个内核态运动态的切换,对不对啊,这个东西叫什么呀,叫做多路不用,是不是出现多路复用了,选择一些,有的我直接去直接执行就可以了,那谁有了是你我一次吊你,你来告诉我多多少个有了。

多多复用的n,就是为了减少云在那台,千万对不对,能看懂这个意思吧,没错,这些都是底层科的碰撞呢,其实这些事情这些东西谁掉的,是你代码调的吗,谁掉的,你一定要明白,我们的程序,我们的逻辑跑在谁身上。

我们的逻辑跑在jvm身上,gbm用什么写的,你的代码是这个java语言,gmm是什么,原写的c语言写的,没错,如果内核不加,这些系统调用不增,不不出现这个nblock这辈子实现不了这些东西。

就像linux能实现n i o,但是linux实现不了a i o,内核上还没有,还没调整一件事情,只有windows才能真正实现a i o好吧,但是这时候注意听,如果你的思路就停止到这个环节了。

觉得ok了,已经可以多多复用了,但是这里边你会发现一个问题,什么问题啊,我每次都给你传很多的文件,棉服,你得给我回,然后我还得挑在里面谁能用,然后再去再去找,再再再再再去调,这个还是有点复杂。

如果把这个复杂度再降低,就是追求更快的速度,就是尽量的做一种伪a l o v l这件事情也是增加再去减少这个过程,我把这个调大一点,这要讲redis io全讲了一遍,然后select有了pull。

我就不讲了,就是后面出现e poo了,你快点说吧,你赶紧说完,我想这个是不是也想听,对不对,不投诉我吧,你们要有人说不想听,我就直接讲redis,但是我觉得redis如果大部分人这块没听懂的话,讲的话。

其实有点有点跳,那时候还得发展,前面的问题你得找到问题,前面的问题是啥,你找到问题了,才能找到这个突破,问题是啥,前面的问题,你学知识一定要找到问题,你才能知道我要学啥,咳咳,这里面一定要明白一个事情。

就是用动态内核态,只有两个菜或者两个空间,你的进程啊有一堆有自己的一个内存空间,里边放着1000个文件描述符,这个这个所有的第一个二进制,你掉内核的时候得传参,你把它传过去,只要数据的拷贝。

听过零拷贝吧,是不是大家在传输的时候都都都期望是零拷贝,不考虑考虑不考虑考虑速度变得更快了,那么其实现在找到问题了,就是拷贝拷贝来拷贝去的数据并不是我说的数据,并不是你i o里面到达那个数据啊。

是我这个内核跟我用户进程俩沟通得i o里面有没有数据这个事,咱俩还得穿着数据跑来跑去,跑来跑去,能不能听懂这个过程,就在决策的环节的时候,文件描述符这样的数据都成为累赘了,当这个成为累赘的时候。

内核如果出现新的东西可以解决这个问题多好呢,有什么问题出现了什么东西。

来看一个一个调用,mm a p,或者是卸载files or davis into memory,挂一个映射map是不是做映射这个这个这个事情的是不是都映射的,然后这个时候它可以解决什么问题。

曾经你的内核有内核的内存地址空间,你的用户进程和应用进程地址空间,那么这时候其实都是虚拟地址空间,那么站在物理内存上面无非就是两个区域,然后这个时候内核的区域你进程是不能访问的,所以需要传参传这批数据。

所以考虑考去,那么怎么规避这个问题,如果内核说得了,咱俩喝出一个空间来,你也能访问,我也能访问,然后你直接在你那个你那,而且这个空间在你这是属于你的虚虚拟的空间里边,你往8号位置写了一个东西。

其实间接写到那个位置了,等于如果你来调一个信标,要用的话,就不需要传单,把这东西拷给我,你只要告诉我8号的位置,然后我翻我通过cpu翻译一下,我就知道是我这边的9号位置,我直接可以读那个数据了,换言之。

我这边如果有一个这个地图空间,我把那个10号的位置放了一个东西,一个文件标符是可以可以读了,然后那个10号位置其实对应的是里边8号位置,你直接就可以通过你那八不是那个那个那个那个7号位置。

通过你读到那个数据,就不要再给拷贝的程减少减少拷贝,说通俗点就是一个所谓的共享空间,没错就这个意思,但是共享空间是通过什么系统调用实现的,你一定要知道,这都是内核来实现的,这个系统交流叫做,mvp。

没错,相当于用动态内容太有一个空间是共享的,当有一个共享之后,有了一个共享之后,那么做了一件什么事情,内核内核怎么去用这个空间运用空间,我们程序怎么用这个空间,在这个空间里边,他做了这样一件事情。

三天不在线,我忘了,这是一个列表,明白什么意思吧,然后这个空间里面放了一些数据结构,这个数据结构里面什么东西啊,我的那我的进程通过一炮一炮可以看啊。

但是e e o是一个整体,它不是一个性,不要用,你直接搜e后七类杂项杂项里面给你解释什么,这个性标用是e泡二类的,有e create易爆的cl呢,evil weight和eo c t l。

这是三个三个系统调用,你可以读一段这段英文就知道怎么工作的对吧。

我简单给你解释一下,你的用户间只需要哎我我我手里有个文文,有1000个文件名符,ok我就写到这个共享空间里去,把这1000个其实自己也就是说一定要怎么自己还会有一个空间,你都有共享空间了。

还需要再准备一个空间去存1000块钱标符吗,先把这一点弄明白了,有了共享空间,这个共享空间其实间谍可以得出一个结论,共享空间就是他自己的空间都在说他可以直接访问,对不对,是不是可以换的。

换位到换到这个这个位置了,这个qq同学来刷不了,这才是本质,你明白共享空间是进行了自己的空间的一部分,也是内核那个迅捷的一部分,所以这时候从这个歌词就不用不用单单独去维护了1000个文件。

描述这个这个这个地理术语,所以进程里边多了一个文件标符,就把这个固定空间的红红数据放往里放啊,往里放往里放,他放的这边只要调性要用,不需要传这个数据,就没有拷贝的过程。

内核是不是就可以看到这个分数一一共都是文件标符的对,然后由红由我们那盒当中,拿着这六根那边符去通过所有的i o这个中断,谁的数据到达了,谁都可能具有了,然后把到达的放到电表里,分到列表之后。

然后这时候如果这边有数据了,你上层用空间是不是可以从列表中取出这个文件变符,直接发生读取dna件名符就可以了,这跟零拷贝没有关系,这跟零拷贝没有关系,这叫共享空间,各自的这个,因为零拷贝是什么意思。

零拷贝是另外一个姓都要用来来来给你看一眼,零拷贝叫做sfs e n写错了,顺着发,synfile是完成零拷贝的,然后sunfl什么意思,也多了一个系统调用,它有一个输出的文件标,个输入的文件标符。

比如偏两个bug和那个那个统计。

明白吧,也就是说再给你画的,举个例子,也就是内核里边多了一个坑,里边,多了一个性,不要用,孙子发,但是说synfile这个系统要用的时候,synfile里面它需要俩参数,一个输入,一个输出。

跟你使用阿帕奇那个i o u t s里边会有一个out,一个in的对象,是不是一个概念,但是你要明白,有他之前发展出这个系统调用之前,它还会有另外两个系统调用,一个是刚才看到read可以读一个文件描符。

有瑞的读就一定会对应有一个什么呀,write写的不对,还是这个应该是right吧,明白吧,你以前程序,如果你有一个文件,啊有一个文件,然后有一块网卡,网卡到内核肯定是一个socket。

socket i o文件,当内核肯定是一个文件i o对不对,这俩是不是两个i o,两个io是不是文件描述符,假设这是fd 3,然后这个是fd 4,然后你之前瑞的时候,你之前的时候肯定read读三。

从三把文件读出来,然后再去掉血写出去,然后这个时候你的这两个系统调用发生在内核身上,那会儿得完成一件啥事,是不是得先瑞的给你,你再ride出去,这能看懂吧,也就是你的数据。

你的文件数据先到内核到八核可能区,然后再由这个这个这个调用,然后这个调用还考虑你用空间,用空间再再尽量再拷回来,然后再发出去,这需要拷贝的过程是需要拷贝的过程的,那么现在有了新的bug之后。

你的程序会是一个什么过程,是直接掉了这一个,然后由内核当中内核拿到缓冲区,直接读它放到缓冲区,然后直接发出去,就不给你的程序考虑考去了,这是sunfile,它跟前面那个一样吗,跟那个m一样吗。

是不是不一样,然后cfl如果加上m v p可以组建一个什么东西,有高效的技术,谁是不是卡不卡,卡卡是不是肯定会有网卡来的数据,网卡的数据来,然后写进了数据之后必须走,你卡玛卡玛什么是基于gmm,对不对。

这一面吧,我多说一点吧,说的有点有点有点开心了,他说这是一个运动关进程,网卡肯定走内核,然后走他他完了之后,它里边一定会使用麦,然后mac里边他是不是可以对files和davis进行挂载,对不对。

它可以挂载到你的文件,直接挂载到文件,然后又因为这个map做的空间是是这个共享空间,内核是共享的,所以这个时候其实你map你这卡夫卡通过map看到这个内存空间,完你写了东西之后,其实内核也能看到。

他直接触发内核就减少系统调用,减少数据拷贝,也约等于是达成了一个他的到时实验零拷贝,但是零拷贝不是两个文件标符之间的内存,倒是用用用户空间到内存空间减少了一个考虑的过程,所以直接写文件了。

然后这是为什么进来的数据,那你打数据的时候可以很快,而且可以存存存到文件上,然后这时候别人是不是有消费者,消费者是不是还得需要把它读出来,消费者是不会拿着拼音来读数据,顺着男人pa要来读数据的时候。

其实这时候走到哪儿是不是走的零拷贝了什么饭,确实走到零拷贝了,零拷贝里边,它sfile的输入来自于文件输出,来自于他,不迷惑吧。

一切的支持来自于底层。

系列 3:P9:【多线程】锁降级过程 - 马士兵_马小雨 - BV1zh411H79h

和大家听我说啊,之前所要及这件事不重要。

可以认为不存在就行了,呃我给大家一个链接。

如果对缩小锁定你感兴趣了,直接去看这篇链接就可以锁降级呢只是发生在gc的时候的一个状态。

但是那个状态你读一下就知道。

其实降级是没有任何意义的,所以简单的可以认为所降级是不存在的。

所以如果有别人问你说你聊不来的所降级。

你就跟他讲,所降级呢在某些特定情况下会发生。

但是这种特定情况下,就是在gc的时候,这把锁已经不被其他线程任何任何人锁锁锁锁锁定了。

好,这个锁可以降级。

可是你想一下都开始gc了,这哥,们呢没有任何人,其他东西。

没有任何其他的,除了那个gc线程访问他之外,没有任何其他线程去访问他了,那你见降低还有什么意义。

没有意义了。

系列 3:P90:【Redis】redis原理 - 马士兵_马小雨 - BV1zh411H79h

画一张图开始引出这个这个这个这个思维逻辑了。

有些基本之王带领的,比如说我如果有一个物理机linux,如果有一个物理操作系统linux,其实这里面是可以有一个release实例,比如他用的就是6379这个灯笼,6379这个灯笼号。

然后呢在这个基金当中,我是不是还可以有一个6380的问,这上面那个支点就是一个计算机当中可以有多个进程,多个redis进程,然后这是一个上面知识点,另外一点我告诉你,redis是单进程单实例的。

把它放大一点,redis是单线程单单线程单实力的单,这里冲不是冲,但处理就这样,类似这样的一个一个名词,但是这时候这是我告诉你的,就是release他自个儿它并不是一个多线程,因为我们去炸了。

它肯定是多线程,对不对,那么re它不是多线程,是单线程的,这个时候又根据刚才的描述,那么并发到来的时候,并发并发一定是很多的请求,很多的请求,那么很多球他在单线单体能单线程的时候,它是如何变得很快的。

如何变得很快的呢,是不是这么一个概念,对不对,那么这时候要注意了,操作系统是不是会有一个内核的概念kl,操作总是有内核的概念的,那么注意你的所有的客户端的连接啊,如果有一个客户端。

你的连接并发一个客户端,可能带来一个链接或者若干个连接,然后所有的连接是先到达哪先到达你的内核,tcp握手,对不对,你所有的连接是新的内核,然后会有很多的所谓的socket。

然后这时候其实redis进程和内核之间使用的是一破,这样的一种多路复用的概念,非阻塞的多路复用的这么一个概念,这个一炮是内核提供一种一种性调用,也就是说其实它是可以由一个进行一个线程。

谁有数据我就处理谁。

且它可以满足一个现象,什么现象,它为什么要讲它redis为什么快。

redis是单进程,是不是用了它一炮了,怕吗不怕,然后所有的客户端发来的数据,因为你内存是不是快了,io是不是慢的内存在这等了好多年,数据中,a慢慢慢就过了一个,然后这时候因为有一炮放到这个map区。

然后他就直接可以拿到符东来,我助理,然后这时候其实间接在它里边完成了一个什么事情,因为使用的易爆,使用的单进程,他直接有一个这个所有的数据到达来的时候是有顺序的,但是这个顺序是加引号的。

这个数据的真正的一事务数据是由你这边的负载来做的,但是这里边顺序强调什么呀,我会一笔一笔的处理,挨个挨个的处理,因为它是单顶层,它不是多进程,不是多线程,它并不是说这里面他到了太燥了。

然后我一个线程处理它,一个线程处理它两个同时进行,那么这样的话有可能两个人都对某一个k一个一个删除,一个创建就撞车了,你得加锁,但是这时候因为我是单进程的,所以你俩一个删一个。

一个删除一个创建或者一个修改,你们俩一定是虽然你可能一块到达,有可能一块到达,但是进了网卡之后,一定还是对挨个儿来的,因为我肯定是便利的,你一套里边那个文件描符。

那个链表我肯定是按着顺序取的。

无非就是先取到谁了,那么这时候其实是由你前端前面再往前的业务能去控制,如果你想保证事物的话,对于同一个k的增量改查,你要负载,让让让一个线程一个链接去发出来,而不能负载的多个跟你使用卡卡一样。

卡卡其实我可以客户端打很多数据,打到一个tp的很多分区里,但是如果创建删除同一个同一个资源呢,我要达到一个topp的一个分区里,而不能再做其他分区的这种这种并行。

这块跟哪个知识其实也很像,跟你n dex知识也可以挂钩,n dex,n ex他要求怎么怎么启动n x n x要满足什么呀,多少颗cpu启动多少个进程,就是worker进程。

w o r k worker进程,一个worker竞争是不是就就可以把它的数据压到cpu的123就缓存了,然后你有多少个cpu,有多少个nx进程,每个每个work进程它使用的是什么呀。

多路复用io,这电源是不是也看到ex介绍i使用了linux 1 pro,现在这是什么意思了吧,其实更主要的是什么呀,一破一破不照不要紧,是同步非阻塞,然后机制下这种什么呀,多路复用。

只有windows才有a i o linux。

系列 3:P91:【Redis】redis及NIO原理复习 - 马士兵_马小雨 - BV1zh411H79h

简单回顾一下,是把ris安装了一下,装完之后呢还没来得及使用。

然后呢就讲到这个io模型这块了,因为要我我让你脑子里有一张图。

就是这个计算机当中这个ready是怎么运行的,就说的就是带了一嘴一。

就讲到l模型这块来了,然后讲完之后呢,跑到后面的时候又讲到这个零拷贝。

结果一炮这块说的还不太清楚,先把那个一炮,因为现在无论你的n这个词啊等等,用的这个一炮的那种io复用的模式比较多一些,啊对不对。

安装资料就在咱们那个大数据的那个get up就有啊所有的安装的步骤,但是那个东西包的话,你你check一下,如果是网盘链接失效的话,然后我再给你发一下好吧。

收回来,然后在这个一炮这个模型这传这个画着这个这个图的眼睛过程。

先是bo就是阻塞的一个美连接。

会抛出一个线程去,然后内核发生变化之后,连接这个sd上就可以使nblock就可以不用堵塞了,那么会发生用户空间程序拿着1000个连接描符,然后疯狂去掉内核,然后这样的话虽然他可以不用抛出很多的线程。

在这多说一句,在这多说一句,就是大家都是搞gm的,在gbm当中,一个线程的内存成本多少,一个线程为什么说前面这个模式当中抛一个线程对应一个连接。

这个就有问题对吧,你知道问题了,就是因为每每连接1000块钱,就1000个线程的那个线程多了,到底哪不好,有人知道一个连接的成本是多少吗,这是一个县城的成本,我们可以控制,我们可以调。

然后呢但是我们只聊啊干扰的内存当中堆是共享的,但是县城站是独立的,县城那个站是独立的,这个站的大小默认可以是一兆,你这b然后呢你也可以调调,把这个这个站的这个线程占的这个单位调小一点。

也就是代表着你的单位内存内可以创建更多的这个线程,其实数上去了,但是你cpu数还就那么几个,其实线程多了,第一在这你要知道d只有两有两个,有两个那个不好的地方,第一线程多了哈,调度成本啊,cpu浪费。

这cpu就正在忙着调度这个事了,消耗在这个内核空间,第二一个内存成本,你想如果你是32位的话,就一个4g内存,以1000个约等于下1000个县城就消耗出一个地区3000个线程内存,就光光把新城站出来的。

然后你还不能对对象,因为堆没还没地儿,你堆怎么也得给个12g,所以这种抛线程的方式肯定不太好,而且一般也会限制,就是无论c的还是做java的,还是做c的,都会控制这个线程的数量。

那么就是要县城不好,所以才有这么一种方式,就是哎我最低可以一个县城或者几个县城来做这些事情,那么这就是非阻塞,因为只要你稍微不阻塞,我吊你询问的时候,你不阻塞的,你就告诉我立刻立刻回话,有没有。

所以这时候我可以用一个线程后路1000个连接,但是每一个连接都要掉一次内核那个调性调用。

所以成本又很高。

这个很高,怎么降低,就无非把这个1000个连接的1000次调用这个数字减下去。

所以才出了这个io多路复用,也就是用我们的一个线程,就是1000个连接服用了一个线程去处理,那么县城这次只需要调用内核给的select这种方式,然后把1000个文文件名传给他。

那他就在那等着内核在内核太,因为掉了他一次,他把1000个变了一遍,然后给你返回几个,然后这个时候注意你这个还得拿着这几个文件描述符,自己调这个锐族数据,或者写出序列这种系统调用。

所以你这边还得是自己去完成数据的写出和读回来,就是这个数据的拷贝拷贝来拷贝去,这个事情就是read read方法,还是用关系调的,那么这个时候其实叫做同步非阻塞,前面那个也叫去。

就是你无论便利有没有数据到达和读数取出事。

都是你现成空间自己做的事情的时候,都是你都是你用空间自己做的时候,那么叫同步的,只不过是非阻塞的。

然后在这种环境下又有一个问题,虽然他解决了这个疯狂迭代这个便利的文件内容符的数量,然后但是它有一个新的问题,就是每次我这写个死循环,每次都要传了1000个,然后他给我编辑一下。

然后返回之后我再遍历这个返回的可用的是找找到可用的,然后去调方法,这样的话用山那个在传递数据的成本比较高,而且完全你自个儿去,每次要传了1000多个标服回来变一个1000多文件标符。

然后等于其实力度不够细,因为你在便秘的时候可能有数据到达了等等,这个就因为右时间上和那个用餐点的切换数据考虑去成本比较高。

所以才输入一套这种方式。

那么除了一炮的话,一炮是一个大的概念,它里面其实有三个标用它select,就一个一个slap标用,那么一炮有三个标用,第一个就是我用户空间当中可以create create,那么在这就不是select。

我在调cray的时候和我肯定给我返了一个一炮,打完全面符一炮,那么返回e破文描述之后,然后未来我用空间有一个连接进来了,我就把这个链接交给这个,写给这个e破的那边有符1p文件标号符。

其实e po这边会准备一个共享空间,是m a ap,明白吧,就就就一个共享空间,一定要明白它们两者的变化是在这块一个非常重要的一个东西,那么有了一个共享空间之后。

它里面只需要维护一个红为数运输空间的每连接1000个连接的话,以前是每调每每学分学这四级四之后1000个传给他,现在是疫情来了之后,1000块钱注册进去就注册了红位数了。

那么注意这个空间里边增删改的操作是内核来完成的,然后查询是两边都可以查,两边都差,尤其我们要查这边这个供电分类的数据,然后当你注册一个链接写进去之后,写个红黑树,然后由这个用空间还会掉一个东西。

对这个一个性标用掉到一po上,这么去写了会掉一个weight,有两个调用,一个是ctrl的调用是往里加,比如a b或者delete我的这个真正的socket文件描述符,然后还有一个方法就是位置。

为什么吧,论文里掉了这种传递,这个新来的炼金阵往里放,放到同一处了,然后用户间就掉位置调位了,那等待等待等待事件,这个其实叫做事件驱动,就是挣来的,因为这个内核里边去完成这你注册这个魂数。

这个这么多文件描述1000个谁注意到了,到了之后就会把这个节点,然后放到链表里去,并维护这个这个数据是写可写还是可读,然后呢你这个wait只要这边有了with就可以返回,你为了从阻塞。

然后你可以变成不阻塞,然后取了个链表,把实际到达那几个文件标符,然后因为这个空间是共享的,直接取出来到你这边,然后你自己还得单独去调read方法,right方法,所以它不叫a i o,千万记住了。

一炮也叫做ni o,它不叫做a i o,什么时候你用空间这个胃的方法掉它了,就是这个给了他一个八分,我不管了,然后数据什么是大的,我也不不用你数据,到时候我才去调这个方法,我是先注册,把说话注册到内核。

然后内核里边某一个来了数据之后,瑞的方法假假设是在内核当中完成这个读写了,然后最终给了你一个消息,或者给了你一个通知,你或者毁掉了你一个,就比如那边准备了一个线程池回调。

把你那个方法要把他那个性能占领去,然后这个时候你的主线成蒙你自己的两边事,根本那边的读数的事,更不是不是不是你去做的,就读这话不是你到了之后才把它吊起的,那个时候他叫a i o。

但是060很难实现这种方式,linux io发展的历程非常复杂,有兴趣可以去看啊,所以这时候一般就停到nl就不聊了,虽然它也有a o相调变方法,但是linua i发展发展的这个路程是相相相当相当复杂。

好吧,就给你补这么一点。

把这个知识补起来就可以了,好吧,ok收io这块就不做更多的细讲了。

那么回来回到这块的时候,当你io的模型能听懂吗。

这个时候要把学有所用,把学到的理论应用到实际场景,比如第一个release瑞兹就会有很多的客户端的很多稍微连接进来,可能一个客户端,比如你准备一个一个一个淘汰,它有一个线程池。

它连过了很多或者是几台机子分布式的很多台去连着一个release,不管怎么样,最终站在这个redis所在机器来说,就是进了sy的很多全打在内核上了内核,这个时候你的release是一个进程进程。

可以调我们的所谓的一炮,然后来便利寻找这里边哪一个客户端,那个sop的那个信息发过来了,然后这个时候注意他re是单进程,单线程来处理用户这种数据,这关于他这个数据的处理的。

但是他锐利自身是就一个县城一个进程吗,不是,没了就是你要明白处理用户了,对数据的操作是它里边的一个线程来完成的,但是他可能还有别的线程在做别的事情,但是这个事情可能跟你的数据没有关系。

所以这时候一般我们就直接说,release是丹尼的单线程来处理我们用户的请求,那么这样的一种单机轮胎线程处理用户请求会有什么好处,这是一个顺序性,但是这个顺序性我再给你强调一下,因为一旦在分布式情况下。

这个数据一致性等等就很重要,而且是一个非常头疼的事情,注意这个顺序是什么,顺序是连接内啊,或者一每每连接,美连接内的命令顺序,这个能听懂什么意思吗,美连接每个连接里面这个这个命令是顺序到达的顺序处理的。

但是如果说比如说这个u k u k为a,那么他也发了一个对a的操作,他也发了一个对a的操作,那么无论你往网络当中跳跃,谁先到达的或者一炮明确的,只不过谁先轮到谁了。

那么其实这两个人对一个的操作为就你很难判定谁先谁后,但是如果是你一个人,它里边线性,而且没有使用多线程,线程线程还是安全的,虽然它可以有多线程,但是只要线程安全,对a的操作,他这边能控制住。

先创建a再删除a,只要他这个能操作的话,那么这个数据是可以保证的,如果他是单线程,这个客户端就是一个线程,就是一个socket,里边也是一个线程,那么这个线程肯定是先发出一个创建。

创建a再发出一个删除a,但是如果他自己这个规则里边是多线程多线程,那么这个创建者和删除的指令是跑前面的,如果线程不安全的话,那么有可能先把这个删除的发出去,再把那个创建了发出去,这块能够清楚。

尤其在思路情况下,多钱的情况下,一无论什么场景,这个数据一致等等,这个数字的情况一定是最头疼的好吧,所以以后开发的时候一定要关注这一点,注意这个小细节。

也就是你在前面会有很长的路,你在做负载的时候,或者在做业务这个这个这个网络路由的时候,你要把尽量的把相同的东西打到一个节点上去,就跟卡夫卡一样,为了保证一个资源的顺序,虽然顺序可能是差差,时间差差很久。

但是尽量用在一个tp的一个分区里,说对于一个k的所有的操作,那么这时候他们到达的是相互顺序是可以保证的。

这简单说一下它的顺序,那么这里面注意它是一个线程来处理这么多,然后每每连接里边是可有顺序的,那么这块完事之后,那么到后面到release 0 release再往后是什么样的。

而且我把客户端拿到这个方向来,因为画到这边就有点看不清楚了,假设一个客户端本来我可能还有一个客户端去访问的release,那么我客户端和rise访问的时候,数据如何传输的,以及redis应该怎么去使用。

系列 3:P92:【Redis】redis使用 - 马士兵_马小雨 - BV1zh411H79h

理论东西都破解了,开始比较实用,比使用的时候注意看。

咳咳咳,这个a6379 和6380,这有两个release竞争已经跑起来了,那么客户端内容是什么,客户端怎么去连我们先讲命令行的客户端app先不说,因为redis其实还是原语的。

你只要会到命令行的那些指令了,那个指令在他的app i当中,基本上可以找到那种a pi那个对应的对应的那个那个调用,那么客户端是用redis gun client这个命令来直接启动,那么直接回车的话。

它默认是连的6379,但是如果你退出的话,1e x退出,你还可以redis杠c l i,然后让h看高度帮助里面它会有一些选项,比如说你连到具体哪一个主机的哪一个端口的,像我们当前这台主机就有两个端口。

639和6380,所以这么一个过程,然后后面讲解的时候可以输密码,然后下面还注意还有一个杠n,就是选一个db database number,然后还有一个杠杆rw,这是要么使用是默认的。

要么使用格式化的这个新技术,大概给你讲,首先先看到一个db在这扩展一下到图上。

那么只要是数据库,学mysql的时候,也会见库库什么的电表,不同的部门可以建立自己的那个库,然后表示隔离的在release里边也有这么一个概念,就是release里边准备了16个,默认是16个库。

默认16个库,也就是有一个0号库,然后还会有1号库,2号库一直到16,但是这个东西可以在你的配置当中去修改,配置文件也一会儿来讲,这个就概念就0号库,1号库,你连接的时候可以通过杠n来指定。

我连那个库或者到内部的进去之后来切换那个库,但是这个零一这个是死的啊,它是不能起名字的。

就这么一个概念,好吧,我们演示一下,然后呢先是用p,然后呢这个6380,这给逗号,那么进来的时候就连6380了,然后呢你还可以在里边,现在这边这边简单设置一下下一个k1 。

这个是比如说k0 号库的380,380里边的,然后k380 ,然后第一个冒号一,这是第一个k,然后value是hello回车,那么这时候get k380 里边就会有一个hello。

然后你还可以select,比如选了一个8号库回车,那么差异在这出现了,你可通过电话,你也发现刚才肯定是走的0号库,默认就进了零,然后现在进了8号库了,8号库里边儿。

然后你get k380 冒号一是没有数据的。

new就是没有的意思,你的k串在哪个区域里了。

那么其他区域是看不到你隔离的好吧,然后退出来也可以通过刚才连接的时候直接给定,比如去8号库。

那么连接是吧,这是简单的操作,没问题,不同的好吧好吧,那么你可以连起来了,那么在使用的时候注意rise里面刚才简单的是使用几个命令。

那么正确的如何去学呢,不需要老师进来之后学任何东西都有一个have回收,那么在rise客户端,注意这客户端里面有这个have客端的help当中,你如果直接说help,它可以告诉你这个help的使用。

有人提出使用方式,第一个help加一个那叫福i,后面可以跟一些组,他把很多命令分组了,或者是直接接到渴望这个命令,他告诉你命令怎么去用,或者help后面可以直接用table,他待会给你提示,给你提示。

现在这这这个前面带符的就是后面各种组,然后后面再出现命令,或者你直接写一个s e,它还能补全,这是他客户端比较人性的一个地方,好了,当这个help这个事情会用了之后。

我们来简单看一眼help用at他分的什么组呢,第一个通用组就是全局的意思,基本配置,那么回归之后,他会告诉你在这个哪些内容是属于这一组的,我们就简单看一眼。

这里面比如剑灵之一比例的删除k你给rik都会删除,然后呢exist pink是否存在,或者是像这种给出定义时间的啊,k的这个存活时间,这个后边讲他这个内存优化都在说这件事情还有可使用的时候。

case是可以接一个这个通配符,或者是这个这个一个一个一个描述吧,可以删掉我们的q有哪些,然后还有move移动,然后object可以查询关于我们k啊。

关于我们k他自身的这个诶怎么黑了自身的一个o b i定义,后面会讲这个proceed,可以将一个你定一下过期的这个东西给它持久化下来等等,这是面向k的,等于这些面子其实都是在面向k做做做些什么事情好吧。

还有一个态度常用的就这几个啊,我就先给你标一下,你走一遍,这是关于常用组的,比如说我在这里面可以简单的用case加一个星号脱位符,然后这个时候可以显示我曾经见过哪些k然后有一个月了。

在这儿注意说一下flash,flash或flash db这两个东西我演示一遍,你知道吧,然后立刻忘掉它,比如fladb回车,然后再case星就没有了,那么你也知道他做一件什么事情,他其实是在做清库的。

这这这种命令在生产当中就尽量的不要使用这个命令,而且一般运维都会把这个命令给你,realme就是你到运营,到你到公司的时候,你可能发现没有这个命令,他给你给自己改名了啊,咳咳好了。

那么这是刚才用的是一个通用的一个组,再来看除了通用组往下,那么说了,还有五种基本的类型啊,五种基本的类型,value指向的是widow,那么vile型也就stream that and table。

有list,然后有set,然后有so sad排序的哈,希然后向下的这种就是消息队列啊对吧,下面不是了事物,这是它的几种几种功能等等的,然后先不说那么一个来看。

先看我们今天先学的第一个string spring类型,那么敲到string类型之后。

它会把关于string这个y类型里边的所有的命令给你展示出来。

一定要记住那句话,就是上面给你标准图,那么比如说在0号库或者拿1号负数吧,你按库分好了之后,这里面有会有k,会有一个k还是key,会有一个key,他因为他raise是是这个键值对的,所以有key了之外。

这个key还会有一个指针指向一个value,那么value里边它是具备五种类型,这个概念要找出来就无所谓行,今天先学哪个,先学spring spa就行了,但是string其实你要把它想成是bat。

后面给你解释啊,就有这个string string其实后面还可以再说他有关于字符串,字符串,字符串或者直接数组的操作,这是第一个反应,有哪些命令还可以基于数值的和位图的,betterman。

这就是rise非常强大的一点。

那么现在我们看到哪了,看到k然后上面这个value,然后根据at的组可以检查出这么多命令好吧,那么刚才比如说我set的时候,我通过set设置了一个k value是hello,然后可以通过get现在取出。

可以通过一个get相等取出,那么这就是关于spring的一个。

那么so思路带回来看这张图你会看得懂,脑子里边一定要明白linux操作系统当中,然后可以有多个re实力,一个release实例当中会有零到这个就是多个库,后面配置文件告诉你能改一个库下都是存在着建筑队。

存的都是键值对存的建筑队当中,然后k其实是个对象,除了可以自身的这个名字之外,还有他的tag类型,然后以及including type类型是用户访问的时候直接看你的方法。

这个这个这个类型是不是具备这个方法操作可以快速返回,你是我这个这个这个方法,这个命令就用错了,不需要去真的去拿那个数,真正参与计算的时候,报报一常可以规避异常,明白吧,然后用qq的话也可以规避。

你后续直接透穿到拿这个字节拿回来直接做计算,这个事可以在前面做一做挡挡一次,对这个用吧,然后这个它是有这个东西,然后什么lance等等,其实你的value的长度,lance当中。

k当中那个对象当中也会保存,因为只要你做增删改这个value了,做资源,同时把这个长度算完之后,后边如果1亿次定完查询的话,不需要再重复计算的长度,长度直接返回,因为你从来在再也没有改过他。

所以就要用这个作者在这个k上的小心思,它让我们的raise虽然是登登记的单线程,但是有一些操作都会预埋下来完成对后续与高并发的查询,那个速度极快的返回基本都是欧冠o e的复杂度。

这是k然后y当中它的release val类型丰富,value的类型的丰富,现在只看到了spring,它的使用类型当中,我给你总结的可以面向最少三三类使用场景,属于字符串的名字上的切割覆盖。

然后还有基本的设置,统一长度还没有数值类型的分类来查,那么数值类型的这种快速的其实有一个场景,这个没有说完,这个也是它很值钱的一个地方,下面这个位图这个场景给写出来了,那么面向那个数值计算的场景。

其实比如就是我们的这个呃抢购商品的叫什么东来着,抢购还有什么什么场景来着,那叫做什么叫什么来着,那这些词突然忘了没对,秒杀,秒杀还有详情页,像淘宝的详情页,详情页当中大部分静态的图片中的信息。

但是他一定会这个后后端发起一个亿,不查实就一不查询查询你这个商品的这个所有的公开数额,然后等一系列东西,所以这个时候如果release没有这个数值,没有intedegree的话,你要到数据库的话。

等于一个并行度的,多个人想去同时对一个生命加加加减的话,必然会触发数据库的事物,对不对,所以这时候其实如果有了这种redis对输出类型的话,可以规避并发下对数据库的事务操作,然后完全由外力,是内存。

内存代替,完全有ridis的内存操作代替,而且这个东西叫做计算项数据移动上上节课其实也说过这个事儿了,这个能看懂吧,像微博当中的,除了这个这个这个香叶微博当中的时候。

还有什么点赞评论等等这样的一个评论数,评论数,好友数,凡是那些看似不是特别重要的数据,看似不需要必须精准的,但是银行里的钱这种事儿,他出了多少钱,利息多少,那个东西必须要染指事物和必必须要持久化存储。

数据可靠性必须要保证,所以这时候在不同的场景下,你要做正确的技术选型,就是这句话,就是他就光一个string,我可以讲出这么多东西来,rise是不是另外一回事儿,现在说的是一个值在观影库里边。

表里边的一个值的变化,使用关系数据库,你肯定得触发事故,在并发情况下,多线程情况下,但是这个值挪到redis里,因为它自身它就是一个进程,一个县城所有的请求增改查,而且计算机数据动。

所以发射站的那个内存,那个地图空间自身上面,所以这个时候他其实是比关税率要快很多的,可以规定一个事物那个那个发起,但是但是如果对redis里边如果多条执行的话,必须先前前面成立,后边后边还还能还能成立。

他对多比明明会组成一个事物,那是那是另外一个事,好吧,没错,这个世界上肯定观影数据库是你们最最能看到的,而且是被公认的,但是这个世界不可能就只有这一种关系型模型,肯定剑之多少的数据库能出现。

就一定都有它的意义,还是那句话,那一刻有没有让你去做这件事,db engines,这个世界上不止不是只有关系型数据库这一种数据模型,并不是所有的数据都必须是主键,然后这种翻译法和三还有很多的模型。

比如说这里边还有我们的建筑队的kiva的模型,然后还有宽烈劣势的这种模型,所以还有涂的,还有持续的有很多,我建议你们回去之后把这个网站这几个模型,尤其会标准的,必须看的,什么是文档存储的,什么是图的。

什么是时序的,什么是关系的,什么是键值的,什么是劣势的,这几个必须要看,你看完这个之后,把这些都背下来,心里边有点有点概念了,什么搜索引擎那种的,他们各自差异在哪,所以面试的时候聊这些东西。

都让面试官觉得你和别人掌握的东西不一样,好像具备3年工作经验,而不是只只是被简单被被被概念被支持的。

好吧。

系列 3:P93:【Redis】redis中value类型--字符串 - 马士兵_马小雨 - BV1zh411H79h

站在字符串的角度,现在开始讲这个外道,站在这个字符串的角度,如果面向字符串的时候,你想一想面向字符串都有哪些操作,面向字符串你可以有操作。

最简单的可以设置,比如set一个k啊,注意这个k并没有类型的区分,只有value才有k,你是要随便给一个k的名字,比如说k1 ,然后y里边比如刚刚给一个hello回车。

然后可以get的k一是它最基本的一个面向字符串的一个,就是这个字符串类型可以设置,可以取出,然后还可以什么help,关于set这个这个at string的时候。

或者是你直接看那个set在set的时候不应该加这个这个这个这个暗缝,他sd的时候可以看出这个sd命令后边除了可以接k接外表,还有相应的可以追的参数,那么前边这个是可以接一个过期时间。

后面以毫秒到后面秒了,这个先不用管,后排有两个,一个是n x,一个是x x n n x x什么意思,就是我在设置的时候,比如设置一个k1 ,然后我想给它变成它那个哈喽,我现在变成圈圈叉叉。

然后后面接一个nx,那么回车,然后就可以返回一个new,然后这时候你get k一依然是holo,那么nx什么意思,是不存在的时候才去设置,这是k一如在这里边没有出现过。

那么你这个size才能把它设置上去,但是一旦k有这个k了,视察无所谓,你再想给它变成吞噬差是不允许的,就是不存在的时候才才让你设置,那么这个时候像什么,它的使用场景是什么场景,比如说分布式锁的时候。

分布式锁没错,那么一一堆人拿了一个re来这个做一个参考,说这堆人都想都想删除一个删一个文件,那这堆人谁谁去删呢,谁操过这个文件呢,一堆人拿了很多链接,对一个单线程的redis发起set k1 。

然后nx那么谁成功了,谁就拿到锁了,剩下的人都返回失败,因为别的人抢了他前面创建了一个k了,懂这个意思吧,然后xx是什么意思,比如说我算一个k2 ,然后给它赋一个值,hello。

然后xx回车也是六gk 2,然后发现没有值,等于上面没有设置成功,x是什么意思,只有存在的时候才可以操作,就是指指它只能更新,只能更新,nx是只能只能新建s只能只能更新,能理解什么意思吗。

就是他们两个最基本的这么一个选项,那么求个单条的get set还有多比的,比如说m3 ,然后m3 去之后,你看他现在很五点之后很人性化,你给出命令之后,他会给你一个灰色的动态提示。

比如我可以设置一个k3 a k4 ,b可是两个,然后这个时候你盖的k3 就是a盖的k4 就是b然后同样的有m set,就有m盖,我可以把k3 k42 个k都给出,分别给你取出好吧。

这就是面向字串这个k的类型的最基本的操作,然后包括这个类型,如果string的时候想想还有什么操作,比如说a pen,我们可以拿死猪这个类型来看一眼,上面会第一个就是append,可以追加,可以追加。

然后big lab这个未读先不用管,然后数值的操作也不用管,然后下边还有get range取你这个k对那个value里边的某一部分截取,然后还有干set取出来,然后放到这个这个取回老的值,设置新的值。

还有哪个概率讲过了,还有,还有一个东西,三个认证可以把一个周串二,这个覆盖到你原有这个k的value的某一个位置,偏移量的一个位置,好吧,我们先统一的演示一下,比如说gk 1,现在里面hello。

我可以用append对我的一个k一追加一个这个word回车,那么gk 1,那么你取出来的就是一个hello world,等于把单子word追加上去了,能理解同学们,然后除了一个append。

还有比如说像这个字符当中,我要取出其中word,把这个watch是怎么取,那么它会有一个get,在这乱整,这时候注意看你要给出k k是谁,肯定k一找到这个value,找到value之后。

它有一个staff和and这么一个概念,那么start at什么意思,你要给出从哪取到哪结束,对不对,那么要数一数最简单的123456空格也是一个,然后第七个七的话其实就是什么呀,从k17 就是六。

因为我们乘以二是从零下标,从零开始的,然后我们取到哪了,然后就是678 90,你发现这个过程现在看是不是网络上取出来了,但是这一过程是不是好麻烦。

你不去数对不对,那么在这儿说一下,它化为一系列的相似的知识,就是正反向索引,正反向索引什么,什么叫正反向缩减,如果你有一系列的元素,如果你有一系列元素,比如像刚才hello,我就简单写一下h。

那么简单写,如果你的这个字符号是h e l的话,然后它有一个正向索引,第一个就是零,第二个就是一,然后以此类推,它会自自动的这个递增,然后就是二还有一个反向的,最后一个就是零这个-1。

然后前边那个就是一个,也就是面向元素,它有正向索引和逆向索引。

所以这个时候如果我们要取的话,这对的话,如果想取出这个or的话,你后边完全可以写一个-1,你只要找到他从那边起了,我就知道最后那么给个-1可以了,如果编的认知如果是从零开始到-1呢。

就是取正向作用的零开始到它-1这个位置,所有的元素,这是真正空降缩引这个东西,同学们,然后再来看k1 ,除了grange,然后还有一个set range,所以人工也是给出k1 。

然后这时候注意给出一个all set outside的话,比如说刚才给一个从这个word变成这个马士兵,怎么怎么去给,那么outset是从六,这是第七个位置开始,后面给出一个歪的那个y轴多长度。

所谓超过长度,它整个会整个整个整个覆盖覆盖进去,会或者做一个扩充,比如给个马士兵回车,那么在gk 1,那么就是从刚才那个位置,从你偏向那个位置,然后把它覆盖进去,这是这是面向字符串最基本的操作。

这个都没问题的,同学们好吧,我没有字串,还有什么操作,你在编程的时候,面向一个字串的类型,spring类型,你还有什么操作是让我想查看它的长度,对不对啊,后边也给你分分。

这个也给你这边他的服务器也给你封好了,就是t r l后面可以借我们的k一回车会告诉你有15个,为什么有15个呀,你get了k10 个字符,是不是一共15个字符,对不对,那么这个取出的长度就取出的长度了。

ok当这个都听懂的时候。

当这个听的时候,注意以上面向周串很简单,常有的操作,这个放的有点占地儿,面向字符串常有的操作,回去我在这儿给你标出来,你自己去补笔记,自己去补,我不给你写完整的笔记,因为太low了,好吧。

这边我就简单跟你说,肯定有set,然后get,然后还会有append,然后还有会有set range,get french等等,一系列的这名字上该有的操作还要取它的长度,取得长度ok。

系列 3:P94:【Redis】redis中value类型--数值 - 马士兵_马小雨 - BV1zh411H79h

那么在这当对redis的基本使用有一个认知之后,那么现在高级的地方就出现了,马上出现了,那么首先进行一个命令,刚才看这个全局命令的时候,一个ta tab比如说接我的k1 ,他会返回什么。

tab是不是看类型的意思,我刚才面前k一调过一些命令,你命令其实都归属于smile组,所以tab k k一的时候可以看这个k它的y值的类型是死于类型,这是一个常识,你用tab命令审视一个k的时候。

可以是死的类型。

为什么,因为它有五种y的类型,每种y的类型都会有相应的什么呀,都会有相应自己的方法,每一种方法是和类型绑定的。

如果你从客户端就是发出了一个非实用类型的方法,想操作这个spring k的话,不用发生实际的操作,他只需要拿你那个方法,对于0k类型找不匹配。

直接给反应报错,这是最基本的一个一个优化,也就是说它这个k里边会登记k里头会有一个属性就得知道加了,除了y轴上面刚才说到指定的一个知识,就要补一个,在k里边会有一个最基本的一个态度。

态度描述的是value的类型,type描述就是y轴的类型,那么除了有一个tap,还有什么东西。

还有什么东西来注意看,如果我用set连青眼库啊,flash d flash,然后我用set首先看一眼help,sin命令,这个set命令一定是取值类型的,对不对,所以说我set一个k1 。

然后比如说给一个99回车,那么现在注意我是刚才set一个什么hello之类的,这k1 hello跟sd 99,那么这时候注意看type k1 ,请问我回去之后,他应该是个啥来看。

如果他们可以用它回的时候是个啥,没错是个string,因为我说了你这个命令是哪个分组的,那么未来这个k的val就是哪个类型的,所以肯定是死神类型,对不对,那么这时候再来看,我算了一个k2 。

然后一个hello,那么这时候不用想,因为你你的命令是什么类型的,所以k2 的tap类型也是损失类型的好了。

这两个都是之后,然后注意看啊,他的tap是绝对外边形,那么k其实它就是一个ob de,在月亮就是oem,除非这个太后也是你客户端,只要掉了这个k上面同学的tag去审视它的话,就告诉你明白了什么类型。

除了他之外,简直是个ob dex,还有一个东西,还有一个命令是审视这个k里面其他的一个元素的,比如说它里边还会有一个o b站的命令。

可以看到e n coding,那么因为ky是什么意思,ob jazz有这样一个命令,在rap当中有o b j的命令,它可以接受一些子命令,你可以通过help,b站,然后ob jack c直接回车吧。

啊可以通过a de后面这个have看不到,我上调一下o b i可以接入指令当中,就有一个including编码的意思,你要给个k那么什么意思,比如ob ject,然后对我们的d n cod。

然后刚才k28 楼注意我回头绕就会显示啥,走会告诉你是一个nb编码的一个string,不管怎么看成string了,因为我刚才k2 是不是一个hello,就是一个死刑,对不对,这个应该认可吧。

没有没有好用,对不对,那么除了它注意看刚才是来个k1 ,如果用object in call in对k1 ,请问回答正应该是啥,是自发的行吗,是不是自重类型来说一下,是不是字段类型。

这应该搭个是int类型好,如果这个你能懂,因为毕竟我刚才我给你演示的时候,碰上你看到了我对k1 c的是一个99,对不对,那么这时候注意看。

一定要记住类当中类型当中五个类型里边有这种例子,还是有什么有int类型吗,并没有int类型,那么这个ink是个啥意思,这个int类型是一个啥意思,它并不是太好注意,你并不是用tap去看的。

这一定要注意了,是有这个对象,我们这指向这个value里面,它的编码说到现在的in q的编码,这个编码如果是运营的话。

这个value的话,它有可能是指令,有可能是印子,为什么,因为面向,因为面向rex使用类型除了作为字符串的操作,还有一个计算的操作,如果发现这个k1 k1 ,你存在九九,如果他发现int类型。

比如说increase对我们的k一作为一个增加,那么这时候跟k一就变成100了。

所以这时候立刻先抬成为一个概念,就是面向string的话,除了自传这些操作指令,他还有一系列数值的操作能看到。

比如说increase increase,你怎么可以给他们读了呀,不怎么样,它是加一,而且你看,increment,然后the integer value of a key by one。

它是固定是晚上加一的,那么除了,除了有加一,还有一个by在后边是可以跟我们那个k1 ,然后后面给出一个加几,比如加一个就是这个22回车,那么再盖的k一就从刚刚100变成122,这是累加。

那么有哪家就相应的会什么decredc don,然后对着k1 ,它就会减一,然后d create,然后然后这时候对着我们的k一减去22就变成99,能加能减,加个y就可以加东西,那么除了可以加整数。

还可以接后边by float,然后对着我们的k1 ,然后加上一个0。5,然后get k一就会有一个小数加进来了,这就进了一个常识,没问题的,同学们,那个e m b s c r什么意思,就前面不用管。

你只需要关注t r就可以了,为啥比如说我给你再设一个sd,就这这么进行提示啊,比如k3 ,然后y轴是12345678 90 11 12 十,30 40 50 60 70 89。

22 122324252627,2829 33 13233343536373839 39吧,设置39个字符,然后这个时候在o v e,然后e偷丁,然后我们的k3 诶,那我再给他一下ak 3。

注意看现在是不是还是s2 类型的啊,刚才39个再给他追加追加几个12345 44左右的,然后在obs in coding k3 ,就这么瞎提示一个roll,一个是这个e m b s r,一个是int。

刚才有这个int类型好吧,这是啥,这是啥,你现在肯定不懂,我要把下面讲完就还可以了。

现在收做减法,所以知道了,我们一直在讲string value的类型,它里边有字串的操作,然后呢还有面向数值的操作,这里都increment decrement。

还有increment decrement by,还有一个这个关于防守的浮点型的计算,都可以在上实现,对不对啊,这个都听懂了,没问题了,那么这时候首先你要知道还有这种操作。

但是什么来自于string,对不对,那么现在问大家一个问题,flash清一下,清完之后,如果看相当于case里边库里不能有了,注意看,如果算是一个k1 ,hello,如果用slost来看k1 。

请问长度多少,前面两个字都铺完了,字画了数值都铺完了,那么现在接着往下走,一个一个过渡的知识,sn k12 楼选的长度多少,长度是多少,长度多少啊,为什么是五呢,回车的确是五,为啥是五。

好像是按照字符的字符个数,一个两个三个四个五个,对不对,是不是五级存的,对不对,但是这时候追上先往上攒,慢慢攒,跟着我自己坑里走,下一个k2 ,如果我设置一个九,设置一个九推车模式成功。

然后ob j然后in coding,然后k2 它们是一种in的类型,那么这时候如果再用scar这个spring lows,然后对k2 的长度进行判断,请问它是几,请问它是几,那么这个时候其实有一些常识。

一些理论就是如果我用一个字节可以表示零到多少啊,或者正负的话,就是0127或-127127,对不对,然后呢在不同语言里边,比如java里边还分为具体的类型,比如少double和int不同的宽度。

那么在redis里边,在redis里边如果它能识别出int的话,那么这个int代表的是java中,就是给他开辟四个字节来存了一个数值呢,还是就开辟了一个字节呢,是不是相关的很多知识带出来,对不对。

你要先把这个知识铺垫一下,这都是常识,为什么,先来看结果是一,明白不是一,对不对,那么这时候注意看啊,如果注意看,如果append对着k2 ,刚才那个九,what a,比如对九。

这个再再一个九或互联网站39吧,三个九回车之后,然后我gk 21定变成四个九不对,四个角,然后再看ob站,然后a扣b然后对我们的k2 注意看是roll认为的,对不对,是不是现在类型。

因为你除了append完了之后,他诶诶这四个九应该应用,为什么还是漏了呢,这是他的方法的问题,但是不要紧,如果increase对着我们的k2 ,是不是这样能加一,能不能加一,能不能加一,能还是不能回答。

挺能的,也能加一,你发现它也能加一轮,也能加一,那么这个时候加上一之后再看,哎又在int特别是int也就说一些方法,一些方法会让这个类型变掉,一些方法提前固定的这个编码,这个in in in的,对不对。

这些都能看懂,比较基本比较基本,但是这个时候要问大家一个问题了,如果在still lose,然后看我们的k2 ,现在蒙是对的,因为我是一步把你往这个坑里带,那么起来的长度多少,都一半了。

一半的时候应该几个长度多少,变成了五,为啥变成了五,为啥鼠标鼠标都是为啥子了,不算完还不算完还不算完还不算完。

再来看,给你演示这么半天就是为了带出来什么呀,注意它的一个二级制安全的这么一个事儿啊,然后这个数值计算。

那么还有一个命令可能没有演示的,这是作者非常幸运的地方了,help spring类型,它里边还有一个比较长的一个get set的gsn,有这么一个小命令,这个gsn什么意思。

就是get three string value of the key and return is old value,不是set,设置你这个k的新址,并把老老值给你返回,很简单。

比如我下了一个k把张飞k一设置成hello,那么get kt的时候肯定是hello,然后这时候还有一个正规名叫set get get set get set get set里面我可以对着k1 。

然后给他一个马士兵,然后注意看回车的时候,如果你qq弄掉的话,他会把哈罗给取回来,老的值给你取回来,写新的值,这是马士兵了,更新了,那么这个那个有啥意思没有。

你要感觉ris在各种场景下为你的这个系统的一个考虑,其实这个位置可以完全不需要开发出来,不是原则性,不需要开发出来,也就是用户直接可以先get了k1 ,然后呢在下面k1 ,那么用户等于既取到老的值。

又更新了新的值,但是这时候你要考虑什么问题,就是成本问题,什么叫成本问题,你发送一个get,再发送一个set,等于在通信的时候发了两个包,两次的i o的请求,当然这个时候其实这两个命令如果合成一的话。

等于在通信上你就发了这么一个命令,过去就发了这么一个命令,过去能理解什么意思吧,同学们就带了一个完整的过程啊,会减少一次i o通通信,这就是做了比较细腻的一个地方,然后除了这些你说的原则性了。

然后看help spring当中还有一个关于多比操作的,多比操作的一个more set,在more set设置很多k的时候,k y k y k value。

还有一个more set是more set nx和ex,比如说像n x n x n x是什么意思,only if none of the key exist,就只有keep that的时候。

是不是才能才能设置,但是这里面前面注意多了一个m就可以设置多个k value,k valk value,那么就是来看走一个过程,比如我先把它清库,把我们的库存掉了之后,现在case都没有了。

那么这个时候如果msn x,然后你可以设置一个k1 a k2 b两个k那么走,然后m盖把你的k1 k2 出来,这个值都能更新上去了,对不对,对对吧,但是这时候注意看,如果你要这么做。

m sn x然后对着k2 给它变成c k3 ,变成d就这样一个操作,那么注意听注意看回车,然后m get k1 k2 k3 回车,那么你会k一是a k2 还是三分d没有变成c k3 ,也没有设置上去。

那么这个时候这个东西才叫做原子性操作,能能能能再多一点吧,也就是你在同时想试着多比剑剑值的那个这个时候加这个m,多比的加了个n存在的时候,他其实想多做多比的时候,它一定是一个原子的,有一个失败了。

有一个失败了,其实这里边谁失败了,k3 可能创建,只不过k2 已经已经存在了,他失败代表了所有人都失败了,好吧。

k3 根本没上去啊,根本没上去啊,好了,那么这就是他们向我们的string这个类型里边的诅咒数数值的基本操作。

系列 3:P95:【Redis】redis--二进制安全 - 马士兵_马小雨 - BV1zh411H79h

下载一个k3 ,如果了a然后这个时候你get k3 就是一个a,然后l然后看k3 也是一个字节奏的,这都没问题,如果append我对着k3 注意看追加一个什么,我们追加一个中国的通字,回车。

然后你get,k3 不应该先盖子落落出来了,赶紧刷一下,k3 ,请问它的长度多少,我刚才看他是不是一个a后面啊,它那个中国的中字怎么那么现在整个长度上是四,不是啊,很多都已经蒙掉了。

那么点演示这么多半天,为啥我给你带出一个概念来,这个二进制安全,好像用红色看不出来,有一个概念叫做二进制安全,就是在read当中自有的一个特征,什么叫做二进制安全,这些low的听上去很高级。

但是glow也就是说在瑞兹进城与外界交互的时候,他与外界交互的时候,课本给他东西的时候,有人给他的字节数组等于,其实二让你想,我们一般面向流有字节流和字符流。

那么redis如果别人通过solit访问他的时候,大家从socket里面拿到的什么流呢,他只拿出字节流,并没有拿字符流,他被我拉特殊球,为什么,因为如果ris它只存字节,没有从字节取个东西。

按照某一编码集转换的话,也就换言之,只要你未来的双方客户端有统一的编解码,数据就不会被破坏,这句话听懂听懂吗,所以叫做二进制安全重要是这个安全这个字。

如果rise它自身除了vivo那种大的类型tab之外,他还有一个真正要动这个音coding,比如说你给了我一个999,我就全称什么什么东西,然后你别人取的时候可能一出我还这个不同不同语言。

因为这是客户端语言很多嘛,那么不同语言的时候,其实对整形的宽度理解是不一样的,就有可能发生截断一出这样的一个错误,没有什么意思,同学们就像在多语言开发的时候,我们更倾向于使用json。

使用charm l这种文本表示数据的方式来交互,而不使用序列化,序列化之后,这个时候大家就必须要自己增加一个什么呀,编码器和解码器,对不对,如果编码器解码器不一样,你那边认为int是四个。

我这边认为int就俩,你那边写的时候成功了,我用一个比较大的一个四四字节,能表示一个特别大的一个数写进去了,然后威尼斯也是四字节,但是这客户端认为这一类型不是该两字节吗,求来之后一出了不够了。

说完显不对了,所以这时候其实rise作为一个非常核心的一个中间一个中间者,他其实有一个二技能安全,它只只只取字节流,所以再来看刚才所有的这个和你想的可能不一样的地方。

第一再清一下fly是,听到之后,第一个数值这块set一个k19999999 ,这是五个九,但是splk一是五,现在就明白了吧,他并没有,虽然他知道ob ob i including,他是int类型。

但是他并不会把它按某一种数据类型给你存,比如按四个字节或两个字节,它就是一个字符,一个字节,一个字符,因为re拿的是字节流,你这个它形容面那个客户端,它的编码也是一个字符,一个字节。

然后直接向字节流去写,所以说先听一部分先听,这能听懂吧,是不是就能听懂,这块能够有,因为保证2d的安全,但是它里边的确会有increase decre这样的一个这个这样的一个计算。

这个计算的过程其实它是要把这一个字节的内存里面拿出来,先转换成数值的。

转成数值之后,然后它会更新我们k上那个这个encoding编码int。

那为什么要加这么一个,因为加了它之后会方便,如果我掉一次including,然后呢把他可能开始绕,可能是字符串,但是我把我把它识别出之后,打转入数字,没有报没有报错,没报异常,没报异常。

你给的参数也是一个数值,我加成功了,只要我计算成功,我就给including更新成int,代表着这个k状态往后都是硬核类型了,下次如果加计算的话,是不是就可以直接拿出来往上加,如果说发现不是int类型。

那么它其实你可以尝试买规律的报错的问题,明白什么意思吧,就是为了一个加速,就是要更新这个这个这个这个这个所谓编码这个这个过程,但是它的编码现在我强调的是,你要看这个长度,它的编码并没有影响数据存储。

这是第一个知识点,还有一个迷惑,刚才那个中国的中字为什么四个字节都不对,是不是为什么四个字节这周就来看set,一个k2 ,一个一个中国,我直接写一个中国的公子,我直接写一个中字中字回车。

那么这个时候我get我现在看成我随便lance看k2 型的长度多少是三个,为什么是三个,那么注意看到这个有关系的是看工具,然后看看在哪啊,选一个看看属性吧,我当前的这个插销连我的reits。

它有一个编码,编码在哪,我在这也就是我这个x shell这个软件和我的ready的通信是u tf杠八的,然后呢,你看我刚才在一定的框架,我试了一个中国的中字,它的长度是三。

然后我给他切成gb k编码及切成jpk回车,这个时候我再set一个k3 ,然后再写一个中国的中字,回车也k了,那么这时候through plus,然后来看我们的k3 ,请问长度多少啊,长度是二。

因为中国的中字在ut方当中是占三个字节,在jp当中jk jk就偏于我们中国自己的语言,所以他其他语言不会顾不会顾虑,所以压缩空间,然后用两个字也可以表示变成二,这都能看懂吧。

也就是说其实他真的走的是字节流,当这个课程之后,然后把客户端退出,注意客户端连接的时候,他默认啊还不能退出啊,再再再来看一眼case星,那么这里边有k2 k3 。

那么这时候注意看get k2 gk 2的时候走是三个字节,因为一这个八,然后盖的k3 是不是k3 ,这边是两个字节,一个三个字节,一个两个字节,这这个这个是16进制的。

它的值它那里边的代码直就是阴天和八当中中国的中字,他这个是值代表的是gj bk编码器当中中国的中字,它的编码这两个听懂之后,然后再退出,然后这时候用怎么进red cli。

然后杠杠这个落后会触发一个格式化回车进来之后注意看,如果你盖了k3 就中的中子,get k2 是这个字,为什么别忘了我现在现在年轻的编码机是不是已经jdk了,如果你只需要知道。

如果不带着他也就是无is只会识别什么呀,只只会识别阿斯玛的超出巴萨哪,他就直接按照16进制给你显示,但是如果你加了这个选项,它就会触发编码集的格式化,也就是说发现了这三个实力进制。

且符合u这个你当前这个编码器的编码规则,就从编码集当中给你找到那个字符就不给你显示三个或两个了,现在这个k2 因为约定了八的1t和八当中,这三个东西在这个当中就是他就水都灌满了,其实最核心就是一句话。

redis是2d的安全的,学了大数据的同学应该更懂,首先还是2d的安全的呀,hbase是不是也是二进制安全的,是不是我们在向hbase写数据的时候,也是要先给他们做序列化,变成一个字节数组。

hbase根本不会去破坏你的编码的,这个时候再看看长度长度这个事儿,它就是长度k3 ,这个点k2 就是三,长度是不会发生变化的,底层就是即便我在这个这种模式下,即便在这个模式下,比如我在一个k4 。

一个中国的中子走,然后star plus一个k4 依然是俩字节,他jpk情况下,也就是说给你上层客户端外围你啥编码,redis不知道raise不知道。

你只要想守raise给他的就一定是你这个客户端先变成字节数组,可以一开始就设成这个int类型,不是自己设置的,是在你设置的时候,你设置了一个k5 ,一个五,然后这个时候o然后in coding。

而且这个时候虽然我告诉你有这个编码这个事了,但是忽略了他会做一些预判断,它是一个int类型,那么这个时候如果他已经判断成int类型的话,你就会来调increase。

然后k5 的时候他就直接可以触发这个计算,而不需要做一个排错的过程,就不需要判断能不能转成直接直接发动计算就可以了,就提速,可以把一个判断转转转行这个过程给他忽略掉。

没错其实说白了就是它底层存的时候就是按照字节去存的,上面只是说在k上面要做一些优化,k上面如果没有赢勾引的话,你每次计算的时候,他都要先走自判断这东西能不能转成,如果发现诶。

你上次的计算是围绕着这个string的一个字节数组的一个类型当中,作为数据数值计算体积成功了,我觉得include直接给标印标准,这个之后你下定论的时候,直接直接对着二进制,然后做累加就可以了。

就反正他就会加速一点,相当的就是适当的会加速这个这个这个加速这个过程,如果他能识别出是这个4g2 的话。

如果你加的话,他就根本就不需要去转码。

直接给你报错,这个类型不符,他不能按计算,是不是大伟这个点一定要get的到啊,这这个其实就是作者比较细腻的一个地方了,作者设计的时候完全可以不用带它,但是带他的话就会稍微好一点。

他可以让他的一些方法的速度变快一些,ok现在什么是二进制安全,听明白了吧,就是未来代表一个什么问题,代表一个什么问题,所有使用rise,你在很多人使用radio,大家一定要在用户端,这个叫什么呀。

沟通好我们的数据的编码和解码,redis里边是没有数据类型的,他虽然是为了客户端,但其实也是客户端稍微带来了一个问题,是在公司当中。

系列 3:P96:【Redis】redis中value类型问题解决 - 马士兵_马小雨 - BV1zh411H79h

你可以试吗,比如说ms k2 k,3d i will get k2 k3 ,那么谁是谁,是触发原则的呀,什么叫原则,你如果就一比的话,谈不上原则,因为它单线程的肯定是原子,那么一定是在多m的情况下。

然后且出现nx时候,那么这个时候肯定是原子的大脸猫,理解了吧,你回想关关机,就你回想你在写ni o的java java是不是他的这个模型选的是epod呗。

你在修的时候是不是也是需要他那个selector,你虽然看他那个战dd k里面的select or,但其实它底层如果发现内核里边有sla,就用slap,没有slag,如果有一po使用一炮。

没有ap就看有没有slap,所以其实是jdk对着操作系统做了一层屏蔽,它给用户暴露的是一个select,是不是道理,但是它底层根据内核优先使用e破,所以那时候你会发现注册完之后,是不是自个儿。

你每次还得循环要这个数据,对不对,等于它底层循环是循环这个位置,其实说白了还是你用户自个儿那边有一个线程得去循环类,或者给你返回了,你就拿出这个图,拿出做的k每个k的拿出通道,然后开始读写,处理完之后。

然后再去wait,它就掉一下就掉下,区别区别怎么会没有区别。

它俩区别多大呀,它俩区别多大了,一个selly,一个e le,这俩区别,你select你用无敌调select吗,这不是炸到的一个select啊,就是内核里边就是操作用c linux c的时候。

如果掉slap的话,你要给他1000个文件名符,但是这个时候如果是一泡的话,你只需要掉一次wait等着就可以了,之前的时候有一个就放一个,有一个放一个,有一个放通过c t,有一个放进一个,放进一个来。

然后后边你只需要轮询调位置等一个事件就可以了,有几个吧,wait 11组特意取消,然后开始开始读那几个处理,处理那几个i o,前面那个是我每次循环的时候都都得压你1000个文件标符告诉你,你啊你我注册。

然后你告诉我有这个1000里面有有有能读的了,有几个,然后我还得把这1000个就过一遍,找出那些k来找这些文件,不是那个那个可以读了,然后再便利他们吊锐的方法。

这边是我来一个压一个来一个等于这1000多,如果select循环了十次,循环了十次select的话,1000要压十次,1000个文章被压十次,那么在一炮的时候有1000个的话。

如果我就是每个每个socket只压一个状态的话,就都压毒,都压血的话,那么其实每个只会压一次c条,只会一次1000个就会就压一压1000个就可以了,不需要再有几点循环十次,这位循环十次也不需要压那么多。

肯定有诅咒的,可以调,你可以调成非阻塞的,但是这个时候这个这个点不重要,重要的重要的是哪一块的变化,就是前面成本比较高,压1000 1000+1000得压一次之后,就为了等链表上有了。

我就取出来那几个文件名符挨个调,或者用多个线程,每个线程发一个,然后这几个线程同时对不同的那个那个那个那个文件文去读,对不对,然后你这个线程又可以再去阻塞这个对链表,这种叫同步的模式,什么叫艺术。

什么叫a i o,什么叫a o,也就是说把这个底层还是这种同步的上层,我可以基于事件驱动,那其实不叫不叫a l,就是就是尾尾l就是感觉我这个用户写在哪的时候,我把一个锐的方法里边要传这个某一个文件标符。

就是某一个socket一个对象,然后呢再接上一个我回调的那个对那个对象的方法,因为面向接口嘛,然后我发出去之后扔给一个县城,那个县城里底层其实还是要走这个位置,只不过你不需要自己的那个线程去处理了。

那个县城,只要拿到之后,然后毁掉你这个方法,但是这时候其实你跟自个儿就脱裤子放屁一样,所以nike就根本没有使用这个这个所谓的为他直接用的是,还直接用这个这个n l o一破这种方式。

因为真正基于事件驱动的ai o在linux当中是很难实现的,光最早先的时候ibm想实现ao,然后后来oracle想实现ao,结果那俩人玩到最后都退出了。

而且最至关重要的你要明白v的这个生态和windows生态不一样,windows是自个儿一家超算另类的生态,然后他是有一个人占主要地位,就是林纳斯这个林克的内核的缔造者。

这个缔造者其实它是有代码洁癖洁癖这么一个问题的,林纳斯他的代码那个有有代码洁癖,他就要求如果想在linux当中开辟的话,这个a o除了是一部之外,它有all in o o l的意思。

就是所有就是统一所有的i o,无论你sk这种的会堵塞的,还是那种所谓的磁盘文件的i o所o都必须使用统一的接口,且这个接口一定是内核系统调用机的,且必须是速度最快的,要超过这种。

但是这个所有的条件压出来之后,这个代码gp上来的话,他就一直在否定所有人给出的l o这个框架,结果呢其实nike也测试了目前这代c当中实现的a o的速度,跟n i u的速度就是一炮。

这种方式的速度基本差不多,因为现在的实现的模式,tfc的代码当中也底层掉的,其实还是e poo,因为它不像windows内存空间访问那么随意,因为linux它更倾向于服务器级别,它是要求安全的。

快这个诚信问了一个问题,就是说哎这么多客户端网来发东西的时候,那么你这边只有一个线程,那么是不是就会处理处理一个的时候,别人都排队等着,的确是一定要注意,刚才说为什么强调一个顺序,但是排队进来的。

但是这时候你就明白了,之前给你讲那个那个那个最近的常识的时候,内存寻址是纳秒,你这个salt其实对于那个网卡,它的寻址是毫秒,也就是说差了将近小10万倍,你除非有10万个连接,我有10万个链接。

大家疯狂的同一时刻到达,那么这时候可能会造成秒级的响应,没错的确15万,你看他那背上能看出来了,这就是小学算法吧,是不是学算法,因为它的选址之间那段级别嘛,而且是技战术移动就在内存里边,也没有磁带。

我还说我就单一个建成,然后呢,等于哪个文件名符,有了之后,我直接就从掉一个位置,把你的这个链接里面拿出来之后,然后8k加一,然后交易之后我手里知道你下一个下一个文件名是谁,因为共享内存嘛。

我就直接注的另外一个文件没有符,又把你从那个命拿出来,你可能是减一就减一,所以那时候其实你看所有的通信的距离,跳这个折板都是很少的,所以说近似于可以达到十十十那个,而且151000秒钟。

15万是为了单机都没有走网卡,我对这个这个还是强调一点,就是它是单机压测的,就是这个计算机当中不需要走网卡,计算机有一个客户端,然后呢有一个redis他俩走的内核都直接回来,这么请求完全纯内存的话。

15万是没问题的,但是如果走了网卡的话,就会降到10万以下,六七万七八万,我脱粉这个问题的确的确点到这个点上了,很好奇内存是啥结构的,不是单道吗,硬盘是扇区,是磁道,内存就是一个线性地址空间。

内存就是一个线性的一个地址空间,其实你就想这么一个事情,如果我给你100个格子,格子长得一一模一样,从格子标号从0~100,然后但是我会给你不同重量的大米,黄豆红米,然后不同东西,然后你怎么往里去放呢。

重量不一样代表体积不一样,所以那时候他们需要的格子是不一样的,对不对,然后这时候还不能把他们混在一起放,那么一定会有浪费,对不对,所以说其实在内存身体这种小格子上面又多了一个叫这个内存页。

然后呢如果100格的从零到十这里边放大米,而且大米的权重比较高,大米是可以去访问别的那些格子,那么这个大米就是内核,剩下那个从从这个11~100这一个小盒里边放红豆,放小米也放,放黑豆。

他们就用工业的程序,这些动物还不都混起来,所以各自有各自的物理空间,这个这个这个这个这个这个范围,但是这个时候其实每个程序它都是靠什么讯地址,讯地址通过cpu的这个m v管理都映射。

单线程是不是规避了线程切换的时候用户太向内核态切换的过程,所以选择单进程,单线程不是不不不完全是不完全是用户这个多个用户进程切换,的确是有性能的损耗,但是这个损耗站在数据一致性面前,对着锁豪算不了啥。

是不是分开了就跟你写java程序一样,你到底是写一个线程,然后用n l o都复用,让每个人的操作都是原子的,还是说我要在引入多线程无用所,让多多多多多多服用进来,数据道理。

所以这时候你就看把两个东西摆在一起的时候,就是做歌手的一个过程,举手的一个过程,这就跟讲集群一样,集群里面为什么是主从集群,主从集群的主就是单单单个嘛,他说一就一说二,就是他不需要和别人协商。

所以主要是主入口,它的性能必须高,才能才能最快,那多线程只不过是并行了磁盘io时间,如果没有网络或磁带o,完全没必要多线程,这个脑子有点大,我这个脑子乱,不管你问啥,我再读一遍。

那多线程只不过是并行了磁盘io的时间,如果没有网络或磁盘io,完全没必要多线程,那么在这注意一点啊,是redis就是在面向网络很多i o的时候都是复用的时候。

如release用单线单线程单进程就可以处理,对不对,然后我们再想另外一个存储数据的就是mysql,mysql是不是处理也是存数据的,但是mysql的数据不是放在内存,它是放在磁盘,对不对。

那么my circle就它更倾向于使用的是那种bo mysql更倾向于使用bo,就是一个连接一个线程,一个链接一个线程,它反而不倾向于使用一破,它需要更多的线程,一个链接来一个县城,为什么。

因为你你去想,如果买sql它要连接进来的很多,进了个10万百万条链接的话,这个请求如果每个请求都要触发磁盘io的话,在磁盘i o这个带宽上就会阻塞住,所以说你好似让很多人进来了,但大家要等很久。

所以请问你前面用e破反而没有意义,还不如直接用bo更省事一点,索引会有预加载,然后索引的叶子是在你的磁盘当中的主干,可以预见到内存的,而且mysql也可以开启缓存,就是比如你发了一个sl。

随便修from a这张表,这个思考你发过一次,他查完了数据,如果你开启了缓存,这个数据缓存在内存里面,主要不它不大,如果你下一条sql长得一模一样,它其实mysql是先预判断你这个sql我是不是刚查过。

查过的话,直接从缓存里返回,后面什么sl的语法书啊等等就不做了,就省了一大块的东西,但是好像听上去开局的缓存可以逼近ready的性能,但是毕竟你mysql肯定是数据大过内存的。

那这可能就四个g买四个数据库,可以一个一个t两个t所以这个时候其实开机缓存,如果表的行比较多的时候,它会降低mysql的性能,反而降低了一个性能了,因为多多一次判断的一个过程和缓存。

这个这个内存内存压这个空间被占用的过程,还不如直接把缓存关掉,所以说呢这个要的是你这个server它会做一个整个sol字符串的,你前后两次sl cav r条件都是都是男前面一个难,后面有难。

你这俩肯定还是一样,那么这个上一次好像都可以用,你这个如果4号万一每次执行结果不一样呢,这个什么意思,那你就说这个数据被改过的了,所以这还是这还有一个问题,所以这个它会蹲不判断。

所以这个你开启了mysql的缓存,虽然想模拟release,充分利用内存,但是反而是不好,的确是这个意思,你像n这就跟你讲n这个时候n dx是不是就是他你有多少个物理核心,他就开启多少个进程,对不对。

是不是道理,而且除了开启相应的这个进程数,还有一个亲密度加一个亲密度,比如我这台电系统有四颗核心,我起了一个release,我会把这个rise亲密到第三颗核心上,然后把所有其他的事情。

其他的那些进程可以让他们在别的这个核心上去跑,那么等于因为你cpu是实验片的,等于更多的时间片,这个3号4号核心就一直在处理外离子,尽量减少他去处理别的进程。

那么这样的话它缓存123级缓存也不会清来清去,所以这是rex才能达到最快的这个所谓的秒级10万或8万,这样的一个速度,就是你让这个进程一直内核调度时候一直跑在哪个核心上。

系列 3:P97:【Redis】redis中value类型--bitmap - 马士兵_马小雨 - BV1zh411H79h

下面开始讲那个未投币的map,嗯,我上节课为什么花了一点时间把你往坑里带,然后为什么你带带出这个二进制安全,最终为什么让你明白他就是一个字节流,而非一个字符流,然后最终为什么让你明白他底层存的就是字节。

其实知道自己这种存储形式之后,为图这个事的好学了。

好吧,比如说自己是什么意思,你看我先清一下库啊,什么叫做贵族,都没有了,那么第一个命令cd,注意这四个b的一个命令,它也归属于string这个vue类型为字符串里面会有这么一个命令。

然后这个命令会给出一个key,会给出一个offset,然后给出一个value,当然这时候注意了,他已经带入这个bt这个位这个操作了,那么这注意听这个outside是二进制位,而非数字节。

数组是二进制位的偏移量。

那么通俗来说画一个画一个东西来说,首先一个字节有多少个2年之位啊,12345678,这是一个字节,对不对,一个字有八个内置位,然后再有一个字节的话,是不是他也会有八个内置位,对不对。

那么这个字节刚才说了,在radio里面的时候,刚才说他这个这个索引的时候,它是面向面向的字符节,是面向字节,它会有索引,也就是说第一个字节的索引奥赛是零,对不对,第二个是不是一了,这个理解吧。

但是注意清注意披露,面向二零中位也有索引,它在二零中位有索引,如果你在使用未命令的时候,使用未命令的时候,它的按键位也是有索引的,它的索引也是从左向右,012345678 90 11。

那么这个就我就很难画了,就是前七个是肯定是起这里边对应他那个位置,就是二进制位,虽然字节是割裂的分开的,但是对于rise里边二进制位,他就想成是一长串。

所有这个位从左向右一直从零一直到他那个位置最大最大。

这个模型先新新到了六数,那么像这里面sfit的时候给出一个k。

你给出这个outside,注意这个outside是哪个,说的是二零之位的outside。

而非字节的offset,举个例子,它的位置我对k1 ,然后注意凹下的是一,然后value那么二零制的value,除非就两种,要么是零,要么是一,对不对,哎我给一个一,那么回车,想大脑里有几个问题。

第1k一的长度是多少,第二它的二进制表示什么东西,有两个问题,先告诉我的长度多少。

没错就是一个字节,那么这时候你要明白这个一是什么意思,这个一是他这个第一个字,第二个字节这个一这个作用吗,不是他说的什么呀,是这个一,也就是说其实它的内存当中是把从左向右,第二个因为从零下方开始。

pc把它变成一了,刚才塞在地上是发生这么这么一件事情。

能理解吧,那么他是个啥东西呢,这个at的福在阿斯码当中01000的一个字节正好是艾福好吧,然后注意再看到那个那种感觉啊,如果,给出k k1 ,请问长度是多少,请问它是一个啥东西,长度是多少。

没错还是一个字节为例,因为七代表的是第八关,所以他不需要开立新的字节,他最小的开闭空间是一个字节,对不对啊,他他他不需要开辟第二个,开辟一个就够了,所以它的长度就还是一个字节,但是它它的数值是什么呀。

你要看你对阿斯玛熟不熟了,是大写的a就是那按这表示表示注意是01234567。

是不是第八个是把它变成了一注意01000001。

现在k一的只有一个字节,就是字节的二进制位,就是01000001,那么它的阿斯码值就是大写的a你可以冷去验证ma,啊什么你就去找大写的a,但谁一说了啊,这里面是,这是十个均值,对不对。

然后这两个数字代表的是前面四位,这个数字代表后四位。

后四位是不是就是一啊,16进制是不是这么这么表示的,因为1248满的话,就是16该进去了,对不对,就是零到15,然后16就到这了,所以这个后边四个正好是这个一,前面这个四是什么意思,124这个位为一。

就是代表四四十一,这代表的是大写的a没毛病。

同学们,然后这个会了,注意在看啊,如果做这样一个操作,set beat对着我的k1 ,然后对他一个九,如果设置成一了回车,那么请问这个长度多少,没错,长度二,因为九已经超过了。

因为他第一个自己的下标是0。35789,已经超过了第一个字节的那个八的宽度,所以程度是因为二,那么请告诉我,根据刚才的知识盖了k一的值的时候,它是什么,gk一的值是什么,没错,是ai,就是这么简单。

他的命令行客户端是可以不全都显示这个这16进制。

如果那个视频均质刚好呢,一个字节能能转成阿斯玛的,给你按阿斯玛给你给你显示能看懂意思吧,因为现在这个k一在内存里边第一个字节就是0100001。

因为我刚刚对九九其实就是八这个七下周10123~789,把这个位置改成一了,它就是at,现在看懂了吗,追风,因为开始的时候你注意我这个整个这个这个命令这个顺序啊,我这个妹子是这么顺序的。

set beat,然后对k1 ,我开始是为一的时候给了一个一,对不对,注意k一可能就是我一个k然后这个第一个是outset,偏亮偏量为一的时候,就是零幺在这打到一个一,这个位置完之后,然后为七七的话。

你就是下下边为七,就是第八个,对不对,就是012360234567,就是第八个在这儿打了一个一,就变成他了,然后下面又执行了一个sat beat,然后bk 1,然后对九打了一个一。

那么这时候一定要知道二进制,这个outset是从整个所有二进制里边从左向右写的,就是012347899的话,是不是第二个第二个自己的第二个位置带一了,那么这时候你的需要天量没有超过两个字节。

其实最终就两个字节,这两个字节就是你的k整个while的内容。

所以这个时候你在get k一的时候得到了a at,因为它是以一个字节来显示的,刚才这个追风这这这个这个过程听明白了吧,嗯ok好吧,这是面向我们的一个206位,可以做这个设置了,这个能听懂,比较简单啊。

月牙是ask ask了,不是u tf杠八,首先你退出去啊,注意看这个。

我给你补上吧,有这么一个基本常识,这个我都讲过,这个字符集,字符集标准的是a s c i阿斯玛字符集,其他的一般叫做什么呀,扩展,扩展字符集,关键是这个扩展的意思,什么叫做扩展啊。

什么叫做扩展啊啊其他字符集不在,对a s c i i重编码,复用复用的时候注意阿斯码有个规律,就是零必须的,然后把1234567,那叫阿斯玛里边第一个第一个字节,第一个币是零。

后面可以从全0~1个全新的变化,代表不同的东西,所以这时候当这个常识,这叫常识,有了之后,任何的程序你自己写的程序,你自己写一个程序,字节流读取,然后你肯定是每字节,每字节判断,你要每字节判断。

如果你读到的第一个字节就是零开口,那么你脑子根本不用想,你都不考虑你自己的gpk还是1等8,直接拿着这一个字节找他,是第一个是零开头,直接去阿特玛把这个字符都显示出来了,但是一旦发现不是零开头。

是一开头,比如一个又一个妈当中有三个一一个零的话,那么你除了这个字节,还在读出两个字节,因为三个一代表用三个字节来表示,然后再把它的前头马踢掉之后,拿剩余的26位拼成一个数值,去你的那个你那个客户端。

那个现在这个字符集当中把那东西取出来,那个字符显示出来,比如中国中子,字符集这块能听懂的同学来刷波一。

好吧,所以这时候其实你会发现很多客户端,你比如说apex当中也是诶那个英文字符,怎么能显示我别的东西,怎么还是那种16进制罗德码似的,就是因为什么软件字符集里边大家都会是阿斯玛,但是他未必去认识其他的。

而且他一般也不会给你做强转。

因为人家放的时候,因为你你你你那是阿里的安全,我要训练客观是那个预定八了,但人家放铃是不是按应该放的,我不知道,所以我就一定是什么呀。

就是按实际实际就是给显示了,但是如果你客户端当中给出什么呀,recline告诉你尽量的拿着我打开的那个就是把它一加,然后我客观现代一直行的时候是啥编码集,那么就尝试着拿着一些16进制的那个不是零开始的。

拿着我这个这个字符集去找那个字符去显示,但是就有可能会出现乱码,因为人家对方可能拿拿了优点,网吧到这里是二进制安全的,还是那个ui编码,就代码了,好吧说的有点多,回来收好,我们在讲我们的两位图。

这件事情现在往里设置,往里设置,这个事情可以可以可以会了,然后再来看还有什么相关其他的,随便这个内容组当中面向b的操作,呵呵呵,这个操作还有什么become,然后big show的这个往后讲啊。

这个这个32出来之后,这个东西比较复杂,今天讲的更晕了,现在简单bedcm的be a beauguration,然后beat pose,还有下边有sb干没了,就这么多,一个来说,你往里设置了。

现在还有一个是beat,pose这个命令big post命令是做什么事情呢,是find first beat,寻找第二位,然后在你的这个字符在哪个位置,他的语法格式用这个命令后面接你单了一个k。

然后呢给出你要寻找的二分之位,但是无无非就两种状态,要么零,要么一,然后你要给出一个区间,但是在这注意了,这给的是star end,它并不是说aset。

那么这个3n说的谁说的是你这个字节的索引。

我们来演示一下,如果用be pose,我要查二零至120制,这个一二进制,这个一在0~0,star 0 n的零,那么请问他会出现吗,beautipose,你要注意这个命令干什么,干什么事情呢。

我是要找的是二分之位,一在这个零到这个零。

这俩零是什么意思,其实这俩零说的是第零个是第一个字节,那么找一的话。

它出现在哪了,是不是出现在一这个位置了,唉走回车。

这,刘我没有给出k没有给出k啊。

是哪个k是我的k一用了啊,你要先给这个k啊,回车是不是在这个这个唯一的位置,在那个一的位置,然后注意看,如果把这个零换成一的话,换成一的话,1~1,那么这两个一star呢都指向一的话。

其实说白了就是第二个字节,对不对,是不是出第二个字节。

那么请问如果查一的话,它的偏移量,它反对的偏量,这个偏量是多少是多少。

要小心回答了是多少。

是多少,没错是九。

他给你返回的是这个一在二这堆二零中位的位置,这么翻译就对了,而不是说在这个字节里,它出现在第几个,返回2g位的时候。

它是全亮的,它是全亮的,那么这时候如果改成0~1呢,它等于多少,他是找到第一个的first。

如果big pose,我要在k一这样的一个二这两个字节这么多二进制状态当中。

我要找一这个二进制第一次出现的位置。

显示在零和一两个字节数的去找,那么回回这就是一就是这个下标一,它找的第一个出现的位置。

这应该都听懂,这个还比较简单好吧,好了,那么除了bp这个bhouse,还有一个是become become become,后面要接一个k。

然后给诸stend,注意start end说的就是什么呀,是你个字节的起始和结束。

然后count什么意思,count它只抗只抗了一,他只count count一出现几次了,那么这时如果对于k1 ,我从0~1这个范围,这个字节单位的范围区内统计一出现了几次什么回回几。

是不是出了一次两次三次。

对不对,那么这时候回的就是一个三,它可以做二进制为一的统计,你给出这个字节的区间,如果给的是00的话,就第一个字节里面两个一,如果11的话,这个时候出现出现过一次,这个一二是这个一,那么接着往下讲。

好那么接着看,除了这些,还有一个是叫做bat option operation,为了操作,那么这个语法的命运是我可以注意注意叫diss,叫目标k目标k后面可以接一个k或者更多的k。

这个目标k是结果是结果不打印了,是要放到这个里面来,那么你参与的k会触发什么,触发一个关于二进制位的逻辑操作,与或非亦或是and or tral或者not学过计算机二进制的。

这应该都知道是不是面向二进制的,或者与或非对不对,抑或单位的单位的操作的,那么举个例子,比如说要注意听啊,我先准备两个,我先把这个库清一下flash,然后我算了一个k1 ,然后把他的一标成一。

然后啊设个壁纸好设个壁纸,然后在sdk一的七标成一,那么这时候k一就是大写的a对不对啊,如果我想得通过200v的操作得到一个大写的b我应该怎么设置,我通过给k2 ,我最终想把k2 你重新带一个b。

但是通过四个b这种方式怎么去设置,然后对k2 的第二个那个v是不是标一个一就可以了,就是零一啥啥的呗,这个这个单我给你讲哪哪用它,然后在sb对着k2 是什么呀,ab是不是能来的。

零一是a10 是不是就b了,一一是不是c对不对,所以说我对它的六这位打一,这能看懂吗,所以这时候加了c2 是带个b,因为后边要用到它做逻辑与后算这个逻逻辑与或的时候用它好了,现在我有kk 2。

一个分别是a一个分别b我给你写出来吧。

因为咱们的确有的人可能对这个,这个的值是不是大写的a,对不对,然后换一个值,后面改成1020制,这是这个零一是110,是不是二,所以它对应的是b了。

对不对,来请问这就是k1 ,这就是k2 ,我要做一件什么事情,d operation operation,然后目标k比如说and key,先先写的是origin是and不and的安慰语。

然后目标k是and key,然后参与的是k一和k2 ,明白啥意思了,然后这时候回车,那么目标把kk安慰语的操作是不是存到目标k里去了,除了标配的话,那么这时候get and key它的值是什么。

请告诉我值是啥暗语的操作的时候直接回到我值是啥,这全答错吗,按位与操作,什么叫安慰语啊,什么语操作有益则益,不是这个有有零则零。

全一唯一的问你琢磨琢磨,这俩如果按位与的话,德国这是个啥呀。

是不是01000000,所以它的值是,明白了吗,现在制作时候都按照这个这个啊这个这个b的b的o o a了吧,如果改一下,如果beat operation,然后给的是一个按位或操作,然后是okey。

然后也是k1 k2 ,那么这个时候我get ok。

那么它里面存的是啥,这是不是c了啊,或操作的时候是不是有一则意了,全因为赢得来,那就是01011。

明白了吧,好了,ok这就是按位操作。

有这么几种方式,那么有人说了,老师你在讲啥,你在讲啥,这边这个知识点很重要,在国内当中最值钱的就这个bm,这是位图,举一个经典的例子,首先我先告诉你的命令,你回去自己整理,这里面是不是会有这个cle。

然后还有bat count,回忆一下,还有beat pose,然后beat operation有这么几种方式。

系列 3:P98:【Redis】redis中value类型--bitmap例一 - 马士兵_马小雨 - BV1zh411H79h

这个位置因为上面都很很容易理解数值计算字段的操作,只为图你们很多人可能第一次听说,所以给大家这个这这儿单独给你做一个笔记,就把场景写出来,两个场景,第一个听需求,第一个听需求,如果你的公司有用户系统啊。

公司有用户,那就优惠点呗,是不是很多用户对不对,哎,然后这时候这个需求是什么,需求统计就是未来这个需求是统计用户的登录天数,且窗口随机什么意思,比如说在电商的公司当中。

电商的网站一般都是说你老板心血来潮,说马上这个今天是8月28828,马上就9月了,那么9月1号往前推一周,9月1号往后推一推一周,这14天所有用户登录的天数方统计一下,然后没过两天被十双11了。

双11的前后保存一下,然后哪天他老婆生日了,哎我老婆生日前后前后几天给我统计一下,就是你的老板会随机的让你统计,指不定哪天就哪天结束这个范围之内,能听懂我什么意思呢,在这个需求下,你是怎么维护jp数据。

支持用户登录的时候登记,且可以把这些用户1年的数据随机窗口去查询,比如就差a这个用户,a这个用户在某一个时间窗口内,他动了几次,那么怎么去处理,是不是处理的解放是有很多,你尝试着多想一想,多说一说。

用你之前的这个思想,过往的经验,你是不是可以拿一个数据库mysql,然后呢创建一张用户登录边,用户每一笔登录是不是可以在里边产生一行记录,然后登记他的时间,哪天登录的,对不对。

然后用户所有动物是不是可以往里灌,但是这时候我想你想一想,这样的存储的时候,是不是就要从存用户的id,因为mysql是关系型数据库,它里边关表示表之间必然有一个主外键,对不对,关联的对。

所以d这个这个id可能就是几个字,几个字节了,至少得三四个节,存一个g吧,能听出来表达这个词,没听说在算这个成本复杂度,对不对,这张表最少每行是不是得存一个日期,再存一个,它哪天登的吗,日期日期的话。

你最少也得准备一个四个字节id,你得准备一个四个字节,这是八个字节,表示一个用户的一笔登录要消耗八个字节,这是第一反应,那么你京东有多少人,每个人1年基本上得有200多天登录这张表的数据是不是极大。

查询的时候,用户老板给出一个随机窗口,是不是要被列,所有的数据成本是不是极其极其的高,怎么优化,怎么优化,大数据处理不需要release。

足以来看,各有思路的啊,各有思路的,你只需要算一个成本,这里没有一个固定的一个数值,有两个固定的数值,第一个固定的数值就是1年有365天或者366天,对不对,我大方一点儿,1年400天。

如果每一天对应一个二进制位,就是从左向右,第一个二进制位代表第一天,第二个位置,二进制位代表第二天,也就是四个400个二进制位,400÷8是50个字节。

用50个字节可以最大记录一个用户全年365天的登录状态,比如比如说这么做,set data,肖恩,我就说,那么我这个人就是key,然后给我的,加上一个一,这什么意思,回车这什么意思,我第二天登录一次。

因为你一定没背20位偏向中心块,对不对,所以是我第二天登录了,然后我过两天之后,如果我的用户再产生登录,你就看哪天了,第八天就下周为七打一个一,我第365天登录的时候要做什么,364打一个一,对不对。

打一个一,我这1年是不是就是第二天,第八天,第365天登录了,只有三笔登录,顶天46个字节,顶天是最浪费的,如果天天登录的话,是不是也是四个字,也是40 46个字节,你就算你你的电商当中有多少个用户。

无所谓了,就用户了,每个用户是bb一路这个数据能登了。

那么最终问题是老板会给出随机窗口。

随机有什么意思,这个任务后最后最后的这几天有没有登录啊,一个字节是八天的,是不是八个人是八天的,那么它的用户最后两周有没有登录,你只需要取什么就可以了,b的count肖恩,然后给出此案的361共是天使。

这么多要除以八个人,那就是负-2和-1,是不是最后两个字节两个字就是最后16天,对不对,是不是动了一次,是不是按照字节的逆向索引,这是统计用户的登录,对不对啊。

这是第一个场景,大概就是四五楼能看懂吧。

我把这个这个笔记给你做一下,其实做的就是set beat。

什么beat。

这就是所作为图。

然后你学过你就去思考一些事情,比如劣势存储啊。

或者什么大量的数据,然后我想猎手就有的有的有的行,有数据好像没数据。

是不是你可以挂一个索引来标识这个用户的某些好友,数据好像没数据。

然后是不是可以外挂一个位,除了一看就是为了一个状态,一个缩影,按这位的缩影了,对不对,然后其实内存消耗很小,好吧,这是第一个需求展现出来的,这个矩阵是一个什么矩阵啊。

上面这个矩阵和下面矩阵是分别长什么样的,上面矩阵是比如说肖恩,然后这里面如果二进制的话,这是key value的话,比如说0101010101,这是在不同的天出现,对不对对不对,然后比如说有消音了。

然后库里边比如还有这个js,然后0101011111,这是它的不同的登录这种这种场景,然后上边对应的是日期上面比如说的这个0102,然后零三第三天,然后零四,把这个最好向右,我就不画全了好吧。

其实你整个公司无论你怎么去设计,就这么点数据,要么就是用户id为key,先为v,要么就是什么,这个时候其实整个内存消耗你都可以算算上边,如果如果上边每一个用户,每个用户是多大的,每用户46字节。

每用户是刚才看是46字节,然后乘以什么呀,用户数和用户数,那么46个字节乘以乘以乘以乘以千万个,十百千万,10万百万千万只拿1000万,大概说1000万的话,就是46乘以它就是最终等于46,46。

然后后面加上,个十百千万十万百万,是不是这样一个,然后这是1k然后兆十兆百兆就知道不是,这是1k然后怎么算1k 10 k8 k照,然后40兆是应该四五十兆的,这是三个三位是1k对不对。

三位是1k然后这是1k了,这是1k 10 k8 k然后兆十兆百兆,400多兆,400多大,400多兆可以放任你京东所有人就是1000万人的全年的登录的明信,然后如果你觉得大的话。

是不是可以把这个用户拿出来,使这个一半的用户放到一个release,另外一个rise的另外一台存,另外一半一半的用户是不是可以单独去统计它们了,是不是可以分开了,能给我吧,下回自个儿再算算,基本上。

但是这东西一定会小于什么呀,第一小于买sql,第二速度快过买sl,因为这个20多倍的计算。

系列 3:P99:【Redis】redis中value类型--bitmap例二 - 马士兵_马小雨 - BV1zh411H79h

不只是主要节省空间,二进制位的操作,在计算机系统当中,cpu速算速度是最快的,你想想如果把它换成观影数据库的话,他肯定读磁盘,第一个产生磁盘o,第二一个读到磁盘之后。

然后他还需要做这个这个读回来的数据的这种编码解码,然后再参与一些计算,而且绝对不是不会是二这种位的计算,好吧,这句话丢失数据,这个后边说,先把这个知识点弄明白了,没错,布隆过滤器也可以。

以其实也用的这个未读这个概念,然后第二个知识点好吧,不是统计这个用户啊,等你们登录啊,换一个维度把这个其实刚才那个二针中位是不是一个矩阵,把矩阵拧一下,旋转一下,权限也是。

比如说我们这个你说的权限权限也是零一数据权限权限,我们是不是就是这个r w x用的是不是scar,这车位就是124,然后就是从0~7这么一个范围啊,收看我第二个需求。

第二个需求就是假如京东这家公司就是你们的,听说京东就是你们的啊,你们就是就是就是那个强子啊,奶茶妹也是你的啊,然后有这么一个有这么一个事情,比如说618做活动,你六八这个这个618这边做活动。

这个活动内容是什么,凡事啊这个这个登录消费之后,这个用户都都要给他们,只要去找你登录,就会送你一份礼物,送礼物,不知道就六八那天会给用户送礼物,那么现在区区是啥大库。

是不是它会有库存度的大库被备货多少礼物,然后假设假设京东有2亿用户,京东一共有2亿用户,6868这天登录就送礼物,登录就送礼物,但是一个人只能送一件,库存中要背多少的礼物,你的老板就这么一个需求下来了。

啥也不说了,背多少,看看你是不是符符合做这个这个这个这个老板背多少啊,有人说背2亿,对不对,那么这时候其实做电商应该有一个最基本的一个常识,就是用户里边分为什么呀,僵尸用户,冷热用户或者叫忠诚用户。

没有什么意思,同学们,是不是你就比如qq号,你们1年有几个qq号,每个人是只有一个吗,尤其是早几年养宠物的时候,怎么那十几个一块在那挂着,对不对,你拿腾讯来说,我这有有有10亿的qq号。

代表就有10亿个人吗,是不是可能是几亿,对不对,所以这时候怎么去做,一般都说一家公司只有销售才能给公司带来利润的,问说你们开发的,你们臭开发的就是花钱的买服务器,然后各种这个这个这个消耗消耗钱的。

但是这时候其实如果你有一套方案可以告诉刘强东说,过往1年或同比去年的这个时间范围内,或者过去一个月春以内,我我们的网站只有1亿的活跃用户,或者只有100万的活跃用户,经常登录,其实根本不是2亿的。

经常登录的用户,你是否能把这个数据拿出来再涨出来一点,比如占了20%,占了30%,你算算,如果一件礼物十块钱,1亿跟2亿就是10亿和20亿啊,中间差值是差十个亿,你你就可以转身问销售。

你能给公司立刻创收十个亿吗,我随便动动手指就可以减少10亿的成本,能get到什么点,所以这时候其实最终的目标压压到哪儿了呀,活跃用户吗,这是经常要做的一个统计活用统计,是吧。

那么要想做图用户统计怎么统计啊,是不是有可能是618有81891 81 81,是不是也是一个随机窗口,也就是你必须你的数据能够支撑未来随意的给出一个窗口。

我就可以算出这个窗口里边到底活用户的具体数量是多少,对不对,那么活跃用户的统计它的本质是什么呀,先把这个需求从题目问题才能知道标准的设计,活跃用户的统计是是一个什么概念,活跃用户的统计是一个什么概念。

比如说,这个1号到3号,假设1号到3号,你要统计活跃用户,是不是1号里边儿有多少人,2号里边有多少人,3号位多人,而且一个人如果连续登录,是要驱虫,也就是说你1~1号到3号位三分范围内。

只要这个人如果登陆了一次,还是都有三次,就算他出现了,是不是道理,那么怎么去设计啊,是不是有一个驱虫的一个过程,怎么去设计用数据库,我就不给你出个解释了,一种很慢。

对不对,那么就拿re来说,怎么去做,怎么来做我然后这时候把你刚才那个位图旋转一下,刚刚为图的二命之位是不是代表的是第一天,第二天,第三天,第四天,第五天,对不对,那么给他选这个这个k是不是用户。

然后历史需要给它做一个旋转,比如说sd 2019年0101这一天这一天的时候,注意后面有多,后边是不是可以,这是p了,这是k那么1月1号这一天这一天是不是有很多登录,每个人是不是会有用户id。

你只需要让所有用户的id映射到你的二支之位上,0号二这支位代表的是谁,1号二支之位代表的谁是不是可以了,比如说咱们约定数啊,我是第二个用户,就是第二个二进制位,然后你们的连老师使用的是第七个二进制位。

那么第一天的时候可能我登录了,我登录是什么意思,是不是下流为一,然后打一对不对,这都没看过,也就是一日七为k,然后呢,这一天里边只有我登录了,然后第二天的时候。

这个2号这一天我是不是有可能登录2号的时候,我连续登录了,然后且2号那天谁呀,袁老师也登录了,轮流上这个过程也就是第一天里边只有我登录,第二天里边我和连老师都登陆了,看见了吧,那么这时候就拿这两个来说。

如果我想算一算1号2号里边的活跃用户数是几个呀,是几个活人无数,是不是就我们俩人应该组中二才对,对不对,那么怎么你怎么变beat operation,目标k就是这个d s t t这是目标k谁参与。

是不是我们的20190101这个key和20190102,然后他们要做一个计算,什么计算,是不是有,是做逻辑语呢还是做逻辑或是不做或预算,最后一项的话,我重复的是不是有1v一了。

是不是变成一个一到目标k里去了,连老师呢是不是有1v1 ,是不是就进到目标k去了,能看懂这个效果吧,就后算之后得到一个结果,key jk这个d4 k里面是不是放了我那个位置,就一个一。

因为就会算我作为两个我的位置虽然有两笔记录,但是不是他不会加上二,他只会按二六位还是一,对不对,零二和那个位置退一,是不是其他位置都是零,所以整个这个p里面206位里面就只有两个位置有一。

然后你只需要做一件事情,是beat count disc key,然后因为我这里面只有这么点数据,我就可以从零到-1这个字节的区间之内回来,俩人忽悠5v2 ,考redis基本上会考这道题。

如果你学了release,如果去面试的话。

基本上会这么问。

这里面是不是用了beat origin为操作。

也用到了beaccount。

那么刚才你问老师教的压制位的命,有这些命令有啥有啥用,现在是不是用上了,零到-1说的是什么呀,那20位参与什么统计,对不对,跟上面那个统计是不是一样,最终是你要拿着,因为没办法。

他是按字节这个范围来提取二分之位,然后做了个统计的,其实说白了,这两个有可能是要深思熟虑一些,深思熟虑一些,这个是不是t的天为key用户,i d为v v用的这几种形式,好吧,要么就是20190101。

然后这里面比如说01123456,然后100,然后2019010诶,没没没有影响吧,0102,然后11010101,先给他靠左,然后现在你看是不是矩阵旋转了一下,矩阵旋转一下,就在那上面。

就是用户id了,无非就是u1 u2 u3 ,每个用户是不是固定会u一就是0号位u u z2 的话就是1号位,u的三的话就是什么呀,固定的3号位,那么显然这个下面比数据当中,用户一直有在第二天登录。

系列 4:P1:【JVM调优实战】从底层的本质揭秘程序的栈和堆 - 马士兵北京中心 - BV1VP411i7E4

O。这是第一次这么来讲这个JVM啊,我我先说一下今天讲课的原则。今天讲课的这个原则呢是照顾基础稍差的同学。当然我速度也不会慢,你要有一定基础的同学呢,你也可以呃是吧?你稍微宽容一些啊。

等等稍微基基础差一点点的那个这个这个同学啊,但是我速度也不会慢,大家放心。好,听我说今天呢我主要给大家今明两天吧,我主要给大家去聊这个GC的内容。今天我来讲这个理论,明天我来讲实践。

我们把它一个作为一个完整营务。呃,听完这个营之后呢,你能达到的效果是什么呢?你可以在简历上写写啥写这个叫熟悉GC的常用算法,熟悉常见的垃圾收集器啊,熟悉常见的垃圾收集器,具备实际GM调调优实战的经验。

就是说你听完今明两天的课,差不多有三四个小时。就直接可以在你简历上写上这么一条来,不知道有多少同学能够意识到,当你在简历上写这么一条的时候,你这份简历。可以多值多少钱呢?Yes。不是。大三可以写吗?

可以啊,没问题啊,这跟你大几没有半毛钱关系啊。可以出去吹牛逼了,不用吹牛逼啊,这个是真正值钱的地儿。我告诉你,3000块钱至少。你在简历上写这个,原来你简历值1500,现在就值18000。好,看到里。

今天开始听我慢慢道来,好吧。今天呢我主要给大家讲呢到底什么是垃圾,怎么定位这个垃圾常见的算法,常见的垃圾回收器。呃,调优的时战我明天讲好吧,调优实战呢比较难,稍微复杂一些啊,说说错了。

其实那个实战相对容易,理论相理论啊相对比较难。我们一点点讲放松了讲。今天我也是第一次这么来讲,我怎么讲呢?我是从那个。最底层的一个本质来跟大家聊。嗯哼嗯う。首先呢给大家呃几十秒钟,你扫一下这张图。

看是不是能理解。Okay。嗯。😊,嗯,我看满天志说工资才3000,没关系啊,听完就6000。人要有梦想,要不然跟咸鱼有什么区别呢?好。又是这张图。对。长途几百年不变。只要是冯诺伊曼结构的。

冯诺伊曼杰优的计算机体系不变,这张图就永远不变。耐克都有张图嗯。每周。哪克还有马老师呢。好看这里。嗯,作为一台计算机来说。怎么样这个程序是怎么样运行的呢?这里是QQ点EXE平时呢它静静的躺在硬盘上。

我想静静是吧?静静的躺在硬盘上。什么时候它执行呢?当你双击这个图标。操作系统老大会把它从硬盘load到内存。好,这过程呢我们叫load。漏到内存。漏到内存之后,这哥们儿会形成一个进程。ok。

会在内存里面形成一个进程。这进程里面包括什么呢?包括一条条的指令,一条一条的数据。然后接下来。CPU会一句一句的一条一条的指令拿到自己的内部来开始执行。需要数据的时候呢,再把数据给读过来。

他真正开始执行了之后呢,实际上他还是需要内存的辅助。好。这个进城的内部到底是怎么组织的呢?好好听我讲,这精神内部怎么组织的呢?呃,这块我就简单介绍到这,没问题吧嗯。可以关一下微信的声音哦,sorry。

你提醒了我。稍等片刻。好了,这下世界安静了。Yeah。是怎么组织的呢?在这里呢我介绍程序的。战和堆的概念。程序的战和真,也许有同学了解过,也许有同学不了解,你认真听就可以了。呃,我们来看这样一个小程序。

这是我刚刚敲的。假如说啊我们自己写了一个main函数ma方法,我在里面是这么写的,是objectO等于new objectject。然后呢,我第二句话呢,我调用了另外一个方法,这个方法叫M。

在内存里面到底是怎么运行的呢?听我说,这就是这个进程里面的一个结构。这个进程里面结构什么样的呢?首先第一点,object O等于new objectject,这里面有两个东西,第一个是这个变量。

这个小O这小O在哪儿呢?它是位于我们的栈空间。好,这里叫做站。只要是冯诺伊曼结构的这样的一个程序。我告诉你啊,它结构都一样的,这里叫做站站是什么意思呢?占站嘛,如果你稍微学过一点数据结构。

就是先进后出先进去的后出来后进去的先出来,它是这样一种数据结构。你可以认为它就是一个桶。你先把这个馒头扔到桶底下去的,你能拿的时候,得先把上面的拿出来,最后一个才能拿出来。好,这是这个占空间。

在占空间里面。首先呢会有一个战争出现,这个战争是谁呢?任何一个方法出现的时候都会有一个战争。任何一个方法都会有一个战争。OK媚方法媚函数。既然是调用 may函数,那么首先在栈里面会形成一个战针。

战针它的英文呢叫st frame。这叫做基于栈的这样的一个一个一个结构啊。其实除了基于栈的结构之外呢,还有基于呃别的的结构。但是基于栈的结构啊,还有基于寄存器的结构。

基于站的结构呢是最常用最简单的、最简洁的java呢就采用了这样的结构。这个程序开始执行,会形成会有一个战产生。注意这个站呢。一个县城一个站。每县城一个啊。是。你看啊当我们呃程序开始运行的时候。

这是我们的主线程了。我们主线程呢就会维护一个数据结构。这个数据结构呢就是一个站。在这个站里面呢,它呃会生成这样的一个呃方法的调用。方法的调用路径。这调用呢首先会生成我们的妹方法的栈。当然。

MA方法的站放到站里面之后呢,叫一个战针,一个方法对应一个战帧。如果说你比方说在没方法执行到某一句话的时候,假如说呢它是执行到这里了。没办法执行到这里的时候,他调用了另外一个方法,这时候会怎么办呢?

会在这里暂停,然后跳到M方法里面去运行。😊,当然这个M方法呃,怎么运行呢?实际上就形成另外一个。战争就是这个M战争,然后指令放在哪儿呢?指令永远放在最上面啊,该执行哪条指令了,把这个指令呢给拎出去是吧?

然后它还有一个非常重要特点,什么样特点呢?就是如果一个方法执行结束了,比如说我M方法调用完了,M方法执行结束了或者没方法执行结束了。它会把它给弹出去,所弹出去是一个形象化的说法。

其实呢就是把站顶指针往下移动就可以了。站顶指针往下移动。站顶指针往下移动,CPU要找的时候呢,就会从下面开始找了,就不会找上面上面就废掉了,所以这是这样的一个特点,不知道我说清楚没有。这很简单啊。

你稍微有一点那个计算机基础的话呢,一说你就应该明白。所以如果这句话object order等于于object,它会首先在这个战争里manin这个战争里面生成一个小O。注意这是那个小O。

但是我们扭出来object放哪呢?就是如果说这是我们弄出来的 objectject,它是放在了我们的堆里面。这是堆空间。所以堆空间是在程序执行的时候,用来动态分配内容的空间。

OK然后这哥俩之间呢建了一个关联,这个小O通过这个小O可以指向谬出来这个对象。好了,这是大体的战和堆的最基本的概念。那有同学可能就会说了,老师,你这你讲这个是要不是讲GC的吗?怎么突然开始讲这玩意儿?

因为这东西啊跟GC的发展呢叫做息息相关。好,我讲到这,大家还能跟上吗?没问题的给老师扣个一,稍微做一下总结,就是每一个县城都会维护自己的县城站。县城站里面放着的是一个一个方法调用。

调用的路径的一个战争的堆叠啊,就是一堆战争啊,M方法掉了没方法调了MM呢,如果再调一个方法,它就在上面再形成一个战争。什么时候这方法调用结束了怎么办?倍儿往外一弹。😊,所以有同学说了,老师。

那这两个有什么区别吗?还是听我讲。😊,嗯嗯。好好,听我讲。老师呃,这个站和堆有有什么区别吗?这里面最重要的一个区别是什么呢?最重要的其一个区别是我不知道大家发现没有作为站空间。

当你占用了站里面空间的时候,它是自动释放的。😊,ok。我再说一遍。作为站里面的空间,它是自动释放的。占空间是自动释放,为什么叫自动释放啊?方法已结束,战争。顶针儿啊顶上那个格就往下移。

你得找下一个继续往下运行的那个地儿去,你得跑到下一个战争空间里面了。所以上面那个战争空间就废了,直接就废了。自动释放有什么好处呢?就是如果你有一些。空间是分配在这里的话,你在这里面占的地儿。没关系。

你不不需要手工释放它,你发现没有?你只需要说这方法一结束,哎,哎哎他就弹出去就就没有了。所以你发现没有?像这个这块空间,虽然说它也占一块空间。😊,但是呢你不用手工去释放它。没必要去释望呢,什么时候失望。

没方款一结束啊,整个就往外一弹就结束了。但是堆不一样,堆是什么?堆是在你执行过程之中自己手工溜出来的。缪出来了之后就会战生产生一个空间啊。占了一块地方,你发现没有?那好。

如果说你这个程序里头不停的扭一个fer循环,不停的往里扭扭扭扭扭扭扭扭扭扭扭扭扭扭扭,你发现没有?有一个很重要的问题,很严重的问题,这哥们儿很快这个空间就没了。是不是早晚就没了,是吧?同学们。😊。

那现在的问题是你怎么去管理这块空间?占空间很简单,只要是方法一结束。好,所有的站的空间就全弹出去就没就没有了。你不用管特别简单,但是堆空间不行,堆空间是你要往里头分配,但是你得负责把它给回收。

回收的意思是什么意思呢?回收的意思就是把这块空间标记成为。可用了。原来呢是你是站着的,被别人给占住了,不能让别人用,比其他程序不能用,其他的语句不能用,其他线程不能用。但是。

你必须得手工的来进行对它进行管理。什么时候呢?你觉得我用不着这个对象了,你就要把它给删掉,删掉的就是做个标记。这这块空间已经可以用了,已经让出来了。不知道说清楚没有?好。

听我说我这个讲的东西呢跟任何的语言呢没有关系,跟语言没关系。任何语言。任何语言再强调一遍。从诞生到现在为止的所有语言。都会面临的一个问题,就是这块空间我该怎么去释放它。我告诉你。

程序之中最难调试的bug就来源于这里。程序之中最难调试的bug,一个是野指针,一个是并发问题。这两大问题是程序之中最最难于调试的bug。好,解释一下什么叫野指针。野指真的意思是很简单。同一个对象。

释放了两次。好,这是什么意思?不能说呃sorry。不能说释放了两次。就是同一个对象。嗯。同一个对象。😔,两个指针,一个释放了。另外一个不知道啊。还拿来用嗯。或者说虽然说同一个对象是是可能是同一个指针。

或者说是同一个指针。不同位置。其中一个其这个对象已经释放了,但是另外一个指针的另外一个位置的指针不知道,另外一个县城里面的指针不知道。好,它依然还在使用,这个是也指针,就是不再指向任何对象的指针。

这就是著名的,有一个异常叫no。Poiner exception。呃,如果你原来学过C语言,CI加语言,经常的这种东西会引起内存的崩溃。我告诉你,这是所有语言所面临的最难调试的bug,包括java。

这个东西是怎么产生的呢?非常简单,给大家看张看张图。我给大家再稍微画一下。再看这里简化一下。同学们听我说。呃,我不管你是任何的语言。😊,假如说我们有两个指针,跟rC跟rV。嗯。好。掉高了。嗝屁吧。去。

嗯嗯。😊,好,看这里,假如这个O和这个P,这俩哥们儿呢同时指向的是同一个对象。那么如果我们程序执行的时候,比方说我在ma方法里面要把这个对象给干掉了。或者我的M方法里面把这个对象给干掉了,给它删了。

那我问你没方方面的这个小O,它指向的是个什么东西啊?纸箱的什么东西,加个就叫地址,没有指针,加个叫引用,本质上就是指针。好吧,我们谈本质啊。不要谈那个那个那个你你不要咬文嚼字,你不要学孔乙己。

非得跟我矫情回字有4种写法。这个东西没意义,理解什么意思就行。好吧,玩文字游戏是最没劲的嗯。这时候这时候就变成空指了,对不对?更有甚者,你这块删了之后,被别人给占了,你想想看会发生什么会发生。

你指向了别人的对象,也许你操纵。我告诉你,你拿到了别人的这块内存里面的东西。以前啊在内存里面偷别人密码,就是这么干的。嗯,好好听我说,这是程序史上最难调试的bug,就是野指针。

这个指针指向了它不该指向的东西,它特别严。这有这个就叫野指针,不知道我说清楚没有?嗯,C和C加加里面呢是永远你要面临这个问题的。也许一不小心你这边删了,另外一个指针还在使用它。

也许你这不小心这边删了其他的程序,或者说其他的程序的部分内容又又又又占用了这块空间了。那么这时候你另外一个指针指向了它不该指向的内容。好了。我现在并没有聊java语言,我现在聊的是所有语言。

就是无论是什么什么语言都要面临这个问题。你要正确的删除这块空间,不能多删一次,也不能不删。还得保证你删完之后,所有人都用不了。好吧。这是非常非常难的啊。我告诉你,这是第一这是第一种特别难调试的bug。

历史上这种bug呢维护起来超级超级难。你知道go语言是怎么诞生的?go语言是原来google为了替代他们以前写过的好多C语言的程序。C语言程序呢写起来也许比较容易,但是维护起来超级麻烦。

bug调试起来特别特别困难,所以他们开发了go语言。go语言呢不再用手工的方式去维护这些内存空间啊,而是调也跟java一样啊,引入了GC。当然这是最难调试的bug之一。

那么第二个最难调试的bug是并发问题,我觉得这个问题稍微一说,你就明白,就是多线程。访问。同一块儿。那种公园。如果这个并发问题,再加上野指针问题结合起来的话,你调试起来就更麻烦了。这里只是一个县城站。

完全有可能我还来另外。另外的一两个。这个是非常有可能的。你想想看。嗯。😊,行了,这个图不太好画啊。😊,这这图呢不太好画。缩小一点儿。给哥们放这边了。完全有可能发生一种什么情况,我这个县成站里面啊。

也有好多好多的指针。好,我指向了这个对象。也许是我这个线程把这对象给删了。也许是我这个线程访问的时候,我俩同时开始写,造成了数据的不一致。好了,我告诉你,像这样的问题调试起来是最最头疼最麻烦的。

不知道大家有没有这方面体会。当然有同学说,老师,我天天写CRUD我是没有这方面体会的,那就没招了,这也是为什么你呃你你你你你你你不应该不能过只关注CRUD的原因。

因为面试里面好多好多的问题都要牵扯到这方面问题了。好吧。

系列 4:P10:【JVM调优实战】CMS天生的BUG - 马士兵北京中心 - BV1VP411i7E4

一一一一。😀嘿嘿嘿嘿。😊,讲点更难的问题。这个问题。是CMS的天生的bug。叫做解决不了的bug。CMS诞生到现在,从1点4诞生。到到1。91。9被清出去了,1。9以后好像就不支持CMS了,我记得。

我告诉你,从1。4到1。9,这个中间这个过程从诞生到消失。它中间有非常严重的天然的改变不了的问题。听我说。呃,十四是吧,我忘了啊忘了14还1。9了。总而言之呢,CMS已经被踢走,踢出去了,不带你玩了。

原因是什么?原因是从它的算法本身上就有非常严重的解决不了的问题。这个解决方案呢叫increment update,但是它这个解问题非常的隐蔽。就是你采用这的算法依然会产生漏标。大哥。来。

我们来看看这个情形。这时候你一定要理解操作系统原理,一定要理解线程它是互相影响,互相进行,而且操作系统的去跑线程的时候是你执行一会儿,我执行一会儿。我们来看呃观察一下这这个这这这个问题啊。

我们假设有一个垃圾回收现程,这个垃圾回收现程呢正在标记A。😊,这个A呢有两个两个成员变量,一个是一,一个是2两个成员变量,A的两个成圆变量。😊,好,第一个成员变量他已经标完了,还没标完。

第二个成员变量就是他的第一个孩子,他儿子已经标完了,他闺女还没有标。😊,那么这个A是什么颜色的?告诉我。这个A是灰色的,因为他孩子还没有标完嘛。哪能ge到的老师可以。自动垃圾空气空间碎片这都小事。

那都是小事儿啊,这个是大事儿。好,我们继续继续看第一个线程标了一半的时候,第二个县程来了。😊,第二个县城是江子的,你知道吧?第二个线种。呃。这个时候第二线城干了一件什么事呢?

第二线城是呃就是我们的业务线程,我们业务线程把这个一指向了白色对象。😊,然后壁纸相低的引用也消失了。根据我们刚才讲的理论,incrementement update。这个。第二个线程呢会把这个对象。

重新扫描一遍,扫描完他的孩子。扫描完他孩子之后呢,把它标成黑色,对吧?有点复杂。M2。这有点复杂啊,我们重新重新重重新来,有点绕。😊,呃,M1呢正在标记A已经标记完了第一个属性,正在标记第二个。

在这个时候,我们的业务逻辑现成把属性一指向了白色对象。然后我们的垃圾回收现城把它标成灰色。第三个啊,另外一个垃圾回收现城,把它标成灰色。但是你注意啊,把它标成灰色,还没来得及重新扫描这个灰色的时候。

还记得我们第一个县城吗?第一个县城认为。我们的孩子一已经标完了,他正在标记孩子2。当他标记完孩子二的时候,同学们,你们想想看。站在M1的角度,他是不是认为A已经标记完了呀?A标记完了。

他是不是就把它改成黑色了?大哥。但是站在另外一个垃圾回收角度,由于你的衣衣指向白色了,你应该是变成灰色的,你已经变成灰色,可是还没来得及扫描这灰色的时候。好。我原来那个县城又把它变回成了黑色。完蛋。

这个地依然扫描不到。Yeah。好,不知道我说清楚没有。Yeah。有点绕。对,这是CMS解决方案里非常隐蔽的问题。M一没见过你,没错。一定会发生废话,这没有没有一定多线成的很多东西都是偶尔发生。

偶尔不发生。要是一定会发生。我告诉你,这个很简单了,就一定会发生的bug特别特别容易去调试的。就是那种偶尔发生偶尔不发生的bug。啊,你就特别难调试,你很难重现,知道吗?对,本来改对了。

结果呢另外一个线程标记完最后一个之后又给他改错了。所以你猜猜看CMS这玩意儿它是怎么做的呢?看这里。CMS的remark阶段,也就是重新标记那个阶段,也就是初始标记,找到根对象并发标记。

同时和业务线程一块运行一块标记进行修正的这个过程叫remark叫并发,叫叫叫叫重新标记,从头扫描一遍,恭喜你这个STW时间依然非常长。这有天生的改变不了的bug。正是因为这有着天生的缺陷。

CMS从诞生到死亡,没有任何1个JDK的版本,把它作为默认的垃圾回收器。那这三色意义何在?三色。这是扫描算法,三色之中的更正CMI采用的increment updateate这个算法有bug。

并不是三色有bug。标记加锁加锁效率就低了,加锁谁不会都加锁得了啊,22亿多个对象加2亿多个锁,恭喜你。你扫描一次之后呢,你可以睡一年。那很多生产商还都是用CMSU那是因为1。5、1。6、1。7没得选。

1。51。61。7。没得选听懂了吗?大哥。1。51。61。7就没得选。如果你想选并发的,就只有CMS可以选。1。7诞生了G one,但是很不幸的是,G one的1。7它不成熟。豆豆老爹说。

G one的3色SATB更完善,没错,三色标记算法叫标记用的普遍算法,它中间会产生漏标的问题。漏标问题怎么更正?CMS采用的方案,incremental update有bug。

G one采用的方案叫SATB叫snapshotd at the beginning?没bug好用。所以。1。8如果你想用并发的,直接G one,不要玩CMS。重要是因为他是并发DC的开创者嘛。yes。

你理解了CMS后面理解G one的时候会非常方便。另外呢,到现在为止,有很多的面试官。😊,他没有听过我讲的课,所以他认为CMS还是最优的。扯淡,因为他不懂,所以他还会问。

所以他找你问的时候都会问你CMS的问题,那我也没招。你总不能怼他,你说你还好给我去听听马老师的课听,以后别玩CMS了。😡,他回头拿大嘴巴子抽你,因为他是面试官,你得照顾他面子。

而不是你而不是他照顾你面子。嗯ん嗯ん。😊,所以CMS会误删对象吗?不会啊,这不是CMSremark阶段,从头扫描一遍。😊,他为什么会误删头像,删不了,放心吧,就是慢嘛,还是那句话,他本来要解决慢的问题。

但是他依然很慢。😊,最关键CMS还有其他bug啊,我就懒得给你讲了。我YP呢专专专门专门讲了啊。😊,CMS到目前为止是遇到的SW时间最长的。一旦产生SEW,我告诉你,一旦产生SW。短则几个小时。

长则好几天。那初始标记还有意义吗?初始标记怎么会没有?初始标记是初始标记找根儿对象啊,你能想啥呢?啊,你们见面是吧,一见钟情这个阶段还是有意义的啊。😊,安卓虚拟机采用CMSW啊,没得选吗?

安卓虚拟机也可以采用别的呀。安卓虚拟机google进行了优化吧,我不知道他那个优化过程怎么样。还有老年代的问题。没错啊,CMS还有老年代的问题,我懒得给你讲了。那个问题一旦产生之后,一卡。😊。

几个小时到几天。P。现在重新标记一遍,会牙其他表吗?大哥。不是这图,我刚给你看完。有有有有这么难有这么。有这么难难难难难难难能难理解吗?你看看他是不是SW的呀,大哥。你拿大腿想想,它要是不SW。

那与此同时也会同时产生这方面问题,那还有意义吗?他这个注音标记。重中扫描一遍,第二阶段不是没用,都得了第一。重中扫描一遍,第二阶段又有用。为什么?因为它梳理了相关的内容,简化了很多东西。

所以重新标记呢也会比在这儿重新标记要快好多。大腿想累了大腿想累了,拿屁股想,拿屁股想想都应该知道啊。那个两个变量的没听懂,哎,那会没听懂就算了。那会儿得好好琢磨,慢慢琢磨。好妈。

我我还要给大家讲J one呢。😊,今天还要讲这 one吗?我靠,都已经11点多了,娘的。时间过得太快了。明天明天也行啊,明天吧,好不好?😊,Okay。到几点都行啊,无所谓了。通交。

我们12点之前的秒杀通宵,你今儿秒杀就浪费了。觉得老师讲的不错的,愿意跟老师学的来就是了。这钱啊真心不是你们自己交,3月之后接茬你们公司的啊,接盘。对你已经接盘的下一家公司替你交的。老师向你保证这一点。

对我们这个团队来说,最容易做到的就是让你涨薪。比较难做到的是让你进。大厂。大厂相对难。但是我们也送进去很多人,包括大专生。今儿送书嘛?今儿不送。等我存了钱就来晚了。去年我们这个课6000多块钱。

今年已经是1万。1万多了嗨,别犹豫啊,越犹豫越涨价,就我们2000多的课时。而且我们课程内容呢主要太牛逼了。就我懒得跟你讲,我主要怕吓到你。

就是有很多人啊抄我们,你知道吗?但是他抄不到核心。

你知道我们核心在哪?我们讲架构师核心在哪儿?不是给你说什么高富质的理论基础技术底层算法啊,你你就自己看一下啊,就这打开之后都是90多的个节点,68个节点,47个节点,我不给你一打开基础设施啊。

eng核心服务的设计,八大项目。嗯,八大项目里边呢,任何一个项目都有我们的技术白皮书。好吧。

呃。涨新的技术体系啊,就直接就直接就是涨新的技术体系。我我我只是拿了这块出来给大家讲的,这样调优案例化实战指导啊。像其他弄呢都没有。就就就不给大家一一介绍了啊,太多。总而言之,家而总之,你放心。

别人家有的这全有他介绍到天上去,别人家有的这全有别人家没有的,这也有。

我给你举个最简单的例子,我们要教你一个架构师,你知道怎么教你吗?就像你要搭一个淘宝12306天猫这样的一个架构,怎么教你?

我是直接拿一个项目落地。没有人这么讲,只有我们这么讲。大多数人都是PPT架构师。所谓的PPT架构是啥样啊?

就是给你画一张PPT嘛,让你看上去特别的牛,落得了地吗?落不了。好,我们是亲自在阿里云上买了服务器。这里面画的每一个图都是我们在阿里云上买的一台服务器。

一步一步的教你搭建这几十台服务器,上百个节点,它是怎么一步一步建立起来的?从。分布式ID省中心配置中心索集群事务集群缓存网关注册中心监控MQES分布式tent系狗。大概花了60万。啊,是不惜血本的投入。

好吧。我觉得啊只有这样只有这样,哥们儿,你才能成为真正的架构师。然后你搭好之后,好好在这个项目基础之上给我做压测。我们的设计需求是达到千万级并发,为什么要达到千万级并发?很简单啊。

淘宝我记得当时大概那个交易接口大概双十一的时候大概是60万的并发。怎么才能到千万并发是它的十好几倍呢?其实你只要把架构打好了之后,做到这一点也很容易。当然,淘宝它自己呢做到60万并发其实就够了啊。呃。

做到这点也很容易,架构搭好就可以。就是我教你手把手的带着你把这架构给搭起来。😊,这才是真正的牛逼的架构师,好吧。当然,语言层级。源码层级像源码这一类的内容课程,最新开的班。嗯。

好。

嗯。😊,源码层级这一类的啊,我基本上讲到的模块都会都会给你讲讲到源码机spring呃,什么ncks,什么tmcaspring cloud全系列啊,这个MQELK N。

然后hospot你像没有人没有人给你讲这种源码,知道吗?就是教你怎么样呃编译一个hospot。

然后呢,怎么怎么怎怎么进行各种各样的性能提升,怎么样进行启动。以及呢我在给你讲垃呃垃圾回收的时候,都会给你带到hopot内部。reislinux内核原码myxico原码polo的原码啊等等等等,好吧。

啊,所以你知道我们课不仅是受学生学生欢迎,我们是那个腾讯课堂唯一only one的腾讯课堂only one的最受欢迎课程。O。与此同时呢,其实。

这是我们我们我们学员给我们的一些评论,大家也可以到网上自己去看啊。1297条评论没有一条是差评。名气实力啊,这套课程大而全内容共一个结果讲到十节课。因为我们是保证讲课质量,我们不计我们不计不计成本啊。

就是说讲多长这件事不在乎。不像线下规定3天就得3天,三天讲不完,我给你讲10天,没关系。量大的同时得到了很高的质量。如果不是认真负责的做教也根本做不到。每一位老师都很优秀,这都是废话。

20多位这是来源于一线达成。帮助你舌走很多弯路,犹豫就会白给,果断等于白给。

94小时之后又加了个追评,买到就是赚倒课程更新令人发指。好,很不错是吧?嗯,做成员老老师算法课啊等等。业界良心,团队、售后服务都是一流的。

好,真心的机会真的能学到。这次跳槽找到工作之后,特地回来评价,他学了200个小时之后找到的工作吧。只自己们那么热,不论大厂还小厂,都能独当独挡一面。感谢训练营方向是吧?相见恨晚100多个小时。

除了受到学生认可啊,我们为什么说做者最受欢迎?除了受到学生认可。

我觉得我们比较牛叉的呢,还是受到我们用人单位的认可,看到了吧?

这是我们用人单位的认可。呃,字节跳动的专供我们马老师同事验证使用的。4月4月13的时候主动找到我们说。看到我们课程,就觉得有不错的学员。来就是了啊,小伙伴们水平到了,全中国一线大厂。

任何一个内推机会全都有。呃,最近刚刚给一个应届生推到了基本上中国一线大厂全部推进去了。看看看我看我我看有他的那个聊天记录吗。Yeah。也有人电脑上吗没有同步啊。看到了吗?

这是这是我刚刚啊这两天刚刚刚刚推进去的。刚刚给学生推进去的。这是百度实习也可以接受啊,然后。给推到百度,推到拼多多的反馈,推到字节的反馈。就一线代场这儿的渠道有的是。每个机构都说自己有内推内推渠道。

其实大多数的呀就是给你把简历往那个HR那一扔。咱们这是真正的内推渠道。我直接给你找到用人的那个你的顶头上司。O。好吧。嗯。我大概给你讲了,刚才讲了这个这个这个这么多啊,大概讲了这几个了。

salpoPS重点聊的CMS它的三4标记算法,它的解决方案,它解决方案的毛病。siro old parallel这相对简单。后面三个我简单给你介绍。11点半。抽奖可以吗?可以的话,给老师扣一来。😊。

还能我操。你今天听了三个多小时课了,你们还能听啊,太扭到了。😊,明天讲G万吧,这晚了,明天明天还讲实战呢,大哥明天讲实战。😊,实在比这更好玩儿啊。我们11点半抽奖好吧,我我我大概给大家介绍大体性的大体。

😊,最粗的方式。

系列 4:P11:【JVM调优实战】JVM调优实战入门 - 马士兵北京中心 - BV1VP411i7E4

好,看这里我们先介绍这这哥们儿,这哥们儿是一个呃比较奇葩的啊,这哥们儿叫epilent,这哥们儿叫做什么都不干垃圾回收器。😊,就什么都不干。空的。这是DDK111才有的。哎,有同学可能就会说了。

老师这这这破玩意儿有啥用啊?😊,他就做个记录,他什么都不干,他就你你你们你你们哥仨啊在这做啥,他都不管,他就他也不他也不清扫,他就拿个摄像机给你们记录下来就行了,好吧。😊,搞这东西有什么用呢?

这东西主要是用来开发JVM的人做第bu个用的。记得到了吗?就是那个我开发的过程,我这垃圾回收器写的怎么样啊?我这垃圾回收过程到底什么样的呀?我用AP跟踪一下。😊,这是第一种用途。第二种用途是啥呢?

第二种用途是。假如我的内存超级大个,我也明确知道我这个程序运行完根本用不了这么多内存。那我干脆就用这种垃圾回收器,你什么都不要给我干。什么时候这程序运行完了,直接结束,整个内存消失就行了。效率极高。

我这个运行过程之中没有任何垃圾回收器在这给我捣乱。Very good。G万这些现在用吗?废话,G万现在都快成主流了,你早就落伍落伍了。你跟着我学永远不会落伍。因为你们你们不抬头看世界,知道吗?嗯。

好ly。CLD成员CLD成务员还等啥呢?千万不要等着后悔啊,几十年后想起来,我本来能够这么走的,就是因为我一犹豫,没有跟着20多位一线大厂的老师带着我飞。还是采用的这样的一个路线,甚至这样惨了。

你来就是了啊,这没有坑。老师呢叫做马士兵是吧?这个机构叫马士兵教也好,直接把我个人名誉啊,什么全堵上去。放心啊,这没坑,你在别地儿呢,就算踩过坑,这儿真没有。你要肯来,就一定能带你飞起来。

20位大厂的一线一线大厂的老师,你就投这偷猪,我也能带你飞起来。我告诉你。啊。好了,不废话了啊。哦,对。秒杀。12点啊,感兴趣抓紧。所以FP了就干这始了,能get到了吗?我们可以继续吗?

你聊D one吧,好不好?😊,G one怎么好玩呢?这晚的好玩点在哪里呢?G1。G one,welcome G one来,我们欢迎G one登场。好,这是G one的核心图。

你会发现G one终于摒弃了分带模型。年轻代、老年代,young old。为啥呢?因为随着内存越来越大,你就算怎么采用并发玩一遍,这个速度也都玩不转啊。年轻的你扫完一次,你总要把整体年轻的扫完吧。

谁的年轻蛋越来越大,我告诉你一次。呃,这种消费的时间,SCW时间依然是非常非常的长,还是不行。另外呢,由于CMS固有的bug,你必须得改进,因此终于诞生了G one的叫做分区算法,叫region。

分区算法叫部分回收,这是它的核心。部分回收是几个意思呢?部分回收的意思就是。我把它分成一个一个小区域。在每个小区里头呢。我只回收其中的几个。你比方说这几个区域快满了。好,我先把这几个回收掉。

这几个区域快满了,我先把这几个区域回收掉。这样的话一边清理区域,一边呢别的这些空的呢再被占用。这样理想的情况是。我永远有空的可用。这叫做G one。需要连续内存放到humanous里面。

humanous就是这个连续的区域连到一起。如果连不上了。开始整理。如果连不上了,开始整理。这就是G one的负利Z。请大家记这个图,这是G one的核心。当然G one呢也有他自己的毛病和bug。

G one的毛病和bug啊,bug没有,主要是毛病。G one的毛病在于哪里呢?G one的毛病其实在于他的一次回收要把年轻贷全都回收完。survivor区伊甸区,他一次回收,要把年轻代年轻代的算法。

YDC全回收完。当你的年轻代越来越大的时候,很大的时候,一次YDC。产生的SW时间也非常长。因此,诞生了ZDC。CDC叫做分页算法。Sa say here。CDC叫分页算分。

而且它的region非常的灵活。这个ZDC我告诉你,这就是g浪的核心。go浪的回收算法就这个算法。ZDC叫0 D Z。zero pauseDC恰号称零停顿。当然他自己的时间呃测算呢据说是一个毫秒啊,1。

68毫秒。有一个网站专门进行过基准测试,2015年测的128G的对内存单次GC停顿最大1。68,平均1。09。那么ZDC的核心在于什么地方呢?

CDC的核心算法叫做颜色指针叫做colored pointer,加上读屏照,叫load barrier。当然它有它这个这个这个同样的也是跟那个呃G万一样,分成一个一个小的区域。

这个小区域呢和呃G万不太一样的是,它这个小区域非常灵活,你可以有一兆的两兆的4兆的、8兆的都可以。与此同时。他不再分代了,不再分年轻代,不再分老年代。不再分老年代啊,不再分cyY吧,不不分这玩意儿了。

他所有权是一样的。它每100个毫秒默认的情况下就会触发一次GC。而这个DC总是找到那些特别满的那些个区域,把他们拎出来,给它回收掉。没有年轻的,没有老年代,越来越简单。this is ZDC的核心。

当然我现在还不能给你解释颜色指针,因为它太复杂了。短时间内很难给你解释清楚。G万每个区域是几兆固定的嘛?11到32之间,你选一个二的倍数,12481632,就这几个不能选别的。ok。好。

我说我说清楚了吗?这样不会产生内存碎片吗?为什么会产生?这样它的碎片不就产生这个区域内部吗?你想想看。就在这个区域内吧,它是复制算法,这个区域活着的,复制到这里来,整个区域回收掉好。就是这里思的核心。

那有同学会说,老师闲念的又是个什么鬼呢?德是daK12才引入的新的垃圾回收器。这个垃圾回收器是谁贡献给?呃,开元开开源开源界的open JDK的呢。这是red hat,著名的红帽。

开发了一个这个ZDC和谢,他们两个的算法叫类似。很类似。这里头只有一个平整,里头是三个平整。其他的都一样,都是这种分分页的O。这两个是一个竞争关系。

CDC是oracle官方支持sha德是开源领域贡献出来的。将来用哪个,目前这哥俩还在竞争之中,到目前为止,sha德的成熟度要比ZDC高。但是ZDC毕竟官方支持,也许将来的发展应该是ZDC为王。

Maybe啊。GY不GY不是不分带吗?我看图上有同学仔细听,作为G one来说,跟面试官聊最精确的疗法叫做物理上不分带。叫物理。不分带。逻辑。粉带。我能这句话听清楚了吗?十文件的。就这块区域啊。

在逻辑上它会属于年轻代或者老年代或者伊恋区呃,或者sviver区,它会属于这玩意儿。但是在物理上呢,它是一个一个的小区域。Yeah。Yeah。Okay。呃,你比如你比如说啊像。

这个GY内存并不是固定的一点区或者old的区。它在这个时刻,它可能是属于old的区。但是当它回收完了之后,下一次再分配的时候。他完全也可以把它当成什么呢?可以当成一点区,注意看这里它最开始是一甸区。

对吧?我们把它回收掉。回收掉之后,下一次开始分配的时候,它可能把它当成O的区了。😊,同样的物理上一块区域。这般用了这万之后,可以理解为东堆空间就不行。大哥,我刚才不是说这问题了吗?蓝风。

我这费劲巴拉跟你说什么呢?😡,逻辑上分担,物理上不分担,还不清楚。你晚我想一想你这晚得理赛嘛,去VIP听吧。另晚我给大家讲实战好不好?我还没有讲实战呢。还没讲实战呢,实战比这个更好玩。

你是你你你得在简历上写有实战经验呀,是不是啊?白皮1克。呃,问问一下咱们小姐姐OK。😊,好,aly,11点半了,咱们今儿就到这儿吧,好不好?明天见喽。See you tomorrow。

系列 4:P12:【JVM调优实战】JVM调优实战 - 马士兵北京中心 - BV1VP411i7E4

。开始今天的课。今天呢我主要讲什么呢?讲JVM的调优实战。JVM调优实战好吧,今天我们主要讲的是实战。

OK废话不多说。我们稍微呃回顾一下,我原来曾经讲过这个DVM的调优呢,你需要理解一些。首先啊以后一说调优第一件事,脑子里立刻浮现。您用的是哪个垃圾回收器?左有垃圾回收器。昨天我讲了10种。

不知道大家还有没有印象。有可能有同学昨天没来,所以呢我是我稍微呢呃我们。😊,回顾一下啊。烧回顾。昨天我讲了十0种蓝球回收器,就是这十0种。这是6呢分别是zeal和seal old,它俩是一对。

plor sky这个p old他俩是一对,注意这歌俩比较特殊。这个料是今年目前大多数的在线的系统默认的垃圾回收器组合。简称PS加PO。调优今天的讲的调优课建立在这哥俩的基础之上。他定有CMS啊也可以用。

但一般来说,CMS现在用的越来越少了。呃,如果用CMS,你如果达不到你自己想要的效果的话,很简单,直接升级G one。🤧嗯。okK还有几种G oneZDC以及什么都不干的epilon。

作为PS加PO来说,它是分代模型,分带模型是什么样子的,大家还有印象吗?分代模型是这样子的,你的内存呢会分成两大部分,分别称之为年轻的young以及老年的old,而年轻代呢又分成三部分。

分别是一甸园区svivve一svivve2啊或者from tosvivve零sve一说都是一回事儿。搞定。今天建立在这个模型和这个PS加PO的基础之上,我来教大家呢调优这个概念。

首先讲一点小小的概念性的东西啊,到底什么叫调优?我跟你说,调优这个词啊,用的太烂了啊,所有东西都叫调优啊,随便动点什么参数啊,也叫调优。嗯,调这个词儿实际上是如果严格意义上来讲呢,它包括好几部分。

什么叫调优呢?从JVM角度,它包括三大部分。第一大部分呢是根据你的需求进行GVM的规划和预调优,这是什么意思?比方说我规划之中,我要每天支撑100万的下单量啊,我这时候要用什么样的机器。

用多少内存这东西呢我们可以叫预规划。也可以叫玉调肉。第二个呢是优化运行这Y的运行环境。比如说你现在这Y文运行环境运行特别慢。가든。好,这个时候你需要定位到一个系统的瓶颈来进行调优。

定为一个系统平瓶颈呢基本上要进行压测,要进行全链路的压测。那么如果是单机的话呢,你只要通过方法进行跟踪就可以。那么如果是分布式的话。

你需要用zip k啊、sky working啊这一类的进行全链路的压测来找出来到底哪个服务特别慢。然后再进行调优。好,这块儿我我解释的,不知道大家还能不能跟得上,能跟上的给老师扣1。

You文 the tuning, yes。你说的太对了,你英文太好了。嗯。来,我们继续。还有一种调优呢是面试之中问特别多的,就是解决这Y运行过程之中出现的各种问题。什么问题呢?

比方说memory leak。比方说OOMOOM的全称叫out of memory呃,内存溢出内存报表这个意思。今天呢我用一个小例子来教大家解决这类问题,你会用到哪些个工具和他们怎么具体的使用。

好好听我说,如果说调优你需要理解很多很多东西的,你需要理解怎么去设设定日志的参数,你需要理解呢怎么啊这个日志。日志怎么去解读它?呃,今天呢我给大家略过一些细节,就像昨天我说的。

希望各位小伙伴们先学最粗犷的东西,然后树干再学树枝儿,再慢慢去抠每一片叶子,你才会变得越来越牛。关于日志这块呢,其实还是挺复杂的。每一个日志你怎么去解读它。我们暂时先略过它。

今天也用不太上用到的地方我大概跟大家说一下。另外呢在工业生产环境之中,一个java程序应该设置什么样的参数,这块也特别重要。有一些参数很多人从书上得来的,实际人家工业环境不可能那么设。

比方说你设置日志文件就设一个,这不可能的好吗?一个日志文件,你很快硬盘就占占满了,所以这根根本不可行,必须是循环的,好多个日志文件不断循环。

比方说你根本就不设heep dump on out of memory error。就是说如果说它OOM之后,你不把堆导出来,那你完蛋你定位不了问题,所以这个也不行。

呃,这块呢我们暂时先把它略过。

系列 4:P13:【JVM调优实战】为什么一个百万级TPS系统会频繁GC? - 马士兵北京中心 - BV1VP411i7E4

说呢我用一个具体的例子来给大家来讲。大家看这里啊,我们那有一个小程序,这小程序呢业务逻辑上我大致解释一下。这个小程序是这样一个业务逻辑。小程序来源于实际。我们有一个小伙伴在工作之中的一个问题的模拟。

JVM调优这这一类问题比较麻烦的问题在于,我很难跟你模拟真实环境,因为真实的环境很可能一个月才出一次。我跟你这模拟一个月,然后为了出这个问题太累了,所以我只能用模拟的环境。

用最快的速度让它fell over叫快速。for fast是吧?快速的让它展现出来它的bug之所在。所以这个小程序是模拟的,虽然是模拟的实际场景之中,它就这样的,你好好听看是不是大致能理解。好。

这个小程序模拟了一什么场景呢?这个场景是在银行体系。或者是互联网金融体系里头进行风控的这样一个模型。风控。简单说,我要给一个哥们儿放贷款,这哥们儿叫博传玉。对。他们家有祖传的玉石藏在柏书里头。

OK说明这哥们信誉比较高,信用额度比较高,我可以给他贷100万。好,换另外一哥们儿,这哥们儿叫st。好,这哥们儿的名字起的太怪异,他的信誉度很低,我只能给他带1000块钱。啊,这东西怎么算出来的?

是根据每个人过去的一些信用情况。信用卡还还还还款的这种及时性啊,借了多少钱,有没有其他的债务啊,是怎么消除的,以前有没有借贷过等等啊,有没有借贷不还的。好,根据这些算出来的这叫做风险控制模型。

风险控制这个小程序就是模拟了从数据库里面取出每一个人的个人信息来套用一个风险控制模型来计算出来。他到底可以给不给他的贷贷款,或者说他的贷款额度到底给多少?啊,这个背景大家听明白的,给老师扣个一。

你 you know your level。去找找一下那个叔叔,让叔叔把你送出去啊,嗯拜拜嗯嗯。没有。好嘞,我们继续啊,看大家看这里。😊,这个小程序呢每一个人的个人信息呢。

我用了一个开 offer来模拟它,只读了信用卡信息。实际当中比这复杂好多。信用卡呢包括它的呃用信用卡额度,包括他的名字,包括他的年龄啊,包括他的生日等等。然后我们用一个。有一个方法。

它呢每次呢都从数据库里面读出100条数据来,读出100条数据来之后呢,加入到我们的test list里面,加入到我们的任务列表里。我们起了一个线程池。

这线程池呢叫s spread to executor。这你学过的话,你就学过,没学过的话,大致理解就行了。它是。固定时长,固定频率的来执行任务的这样一个线程池。在这个建程池里面有50个线程。

然后每隔100个毫秒执行一次任务。在这个任务里面,以固定的频率拿出每一条数据来。每一条数据拿出来来进行计算。大概就是这么一个模型。哦,这个程序呢你理解也行,不理解也可无所谓。

我现在给你把这个程序运行起来,我直接告诉你这个程序里头有毛病,有bug。我举个例子稍微复杂一些,我不想举那种特别简单的。你比如说拿一个list不断的往里扔。对象,然后一会儿就内存溢出了,这个太简单了。

你要跟面试官说,你说我有实际当中调优经验,面试官肯定会问你啊,你实际当中什么情况下需要调优,那遇见了什么问题呢?你跟人家说说有一成语员,反正不是我写了个list,不断往里扔,从来不往外取,很快OOM了。

你如文肯定拿大嘴巴子抽你,这也太简单了,好意思拿出来说吗?😡,可是即便是这样。确实在实地生产环境之中,真的有人犯这种错误。由于业务逻辑混杂在其中的时候,程序就会显得特别复杂,就有可能会产生错误。

这没招了。

但你尽量不要说这个太low太low了。好,我刚才讲这段能跟上吗?能跟上给老师扣一来。😊,你不要太low啊。three local内存泄露那个太高大上了,我觉得你未必能cover的住。

你做什么写了sloc它怎么产生的内存泄露?这个你未必能cover住。不须。好的,看这里。Yeah。我先把这程序给刨起来。这小程序呢我加了几个参数,看他能不能认识啊。第一个参数呢叫杠XMS。最小堆大小。

第二个呢叫杠XMX叫最大堆大小。printnt GC运行过程之中,把我们垃圾回收器的日志输出打印出来,最后是我们的程序。这里问大家一个问题,为什么我设最小堆和最大堆设成同一个都设200兆。最小跟推蛋。

不一般的情况下不设成一样的吗?为什么?晨晨前面没听着,太遗憾了,没关系,不耽误后面听。不用扩容,没错,防止内存抖动。既然你明确知道我的应用程序会占到200兆内存,直接给它分配200。

不要让它没事涨来涨去啊,涨一点涨一点涨一点,涨到最大之后,如果用不着了,又往回缩,缩完了之后又往回涨,还消耗资源。ok。盖到这点之后,我们教会住。这个。应用程序啊。

我们的java的这个进程就开始跑起来了。下面呢我开始是教大家纯实战的内容。嗯。嗯,排练一下。嗯。好,我们排列它一下啊,这样我们看的会更加清楚一些。呃,我们右最右边这窗口里头是我们呃现在正在运行那个程序。

这个小程序呢时间一长它会出各种各样的问题。目前为止呢还没出问题。目前呢它只是展现出来了,说我产生了一次GC。这次E次GC这是什么意思呢?嗯。又应该是怎么给他放到最大嘞。

Well。

。对。我把这窗口呢还是。垂直排列水平排列合并所有吧。这样我切切一切吧,让大家伙看得更加清楚一些啊。

重新运行一下这小程序。贵州。回州重新运上这小程序啊,这个排成三个窗口,不能把信式信息显示完全,看上去也很别扭。嗯,当们运想起来这个小程序之后呢,你会观察它的小程序呢会产生一些日志输出。

这些日志呢你看大概大概是能看明白,我稍微解释一下。这个输出日志输出的是比较粗的日志,并没有输出很详细的。如果输出很详细的,我需要跟你解释半天。还是那句话,我们先略过一些细节。大家看这里。

它产生了一次GCGC产生的原因叫allocation failure。什么意思啊?分配失败。那意思就是说我有一块内存被占满了。好,这个这个DC叫YDC。在年轻的DC。然后这次回收产生了什么效果呢?

原来我的年轻代占了54兆。接下来回收一次之后。回收成为一兆,说明回收了53兆。哇,这次回收的效果很明显啊。😊,然后我们总的GC的呃总的堆大小是20兆啊,200兆,sorry200兆。嗯,时长是多少?

这块我大概说明白了吧,有没有谁在这块有疑问呢?没问题吧,没问题,给给老师扣一啊。嗯。

系列 4:P14:【JVM调优实战】定位JVM问题的实用参数设置 - 马士兵北京中心 - BV1VP411i7E4

加一些最基本的一些常用的命令线。作为java来说,最常用命最常用的命令,当然就是java是吧?好,我们下面来聊一下java的参数。java回车,你会看到作为一个java命令,它后面可以跟哪些个参数?

我先说第一点,就是当我们一敲java的一个命令的时候,它就会启动一个java虚拟机。以前老我同学在这里头犯糊涂,说老师我起了一个javaT1,又写了一个java T2,这这是几个虚拟机啊?两个。

只要你敲一个java命令,就会起1个GVM。这个JVM专门给他服务。这个JVM专门给他服务,你调优的时候不能两个火在一起调啊。这件事很难很难理解吗?很容易啊。好,大家看这里,作为java来说。

它本身有一好一堆的参数。这种以横杠开头的叫标准参数。标准参数没有多少。看上去呢也并不太难理解,但是你不要忘了,这里还有一个杠X开头的,这叫什么non standard non standard。

非标参数。非标准的。所以你需java杠X回车的时候。

它会把非标参数全都给你列出来,像杠Xmix杠S interpretpre这个我在VIP课里有讲过,像什么diagnostic啊,nonclass dC啊等等等等。

这些杠logDC这都是设置你的GC的文件的等等。杠XMS XMX我们都设过了。好,听我讲这个叫非标参数,像这些参数都是可以用于调优的。但是真正调优用到的东西是以杠XX开头的。但是很不幸的是呢。

这个杠XXX开头的这些参数,它是没有一个专门的文档给你列出来。如果你想知道这些参数到底包括哪些。用。这个东西print。Flas。Final。

friend flies final叫打印所有的参数的最终值。我们后面不跟class文件名,直接敲一杠version。我们看他有多少呢?当然你是不知道他有多少。

来试一下。这个杠XX开头的参数非常多。

OK大概是有这么多屏。到底有多少呢?

WC杠L回着。好,一共有728行,透除我们这些特殊的信息,大概有700个参数左右。

恭喜你啦。知道为什么java调油比较值钱了吧。H。

不过呢你们也不用心慌,作为老师这么体贴的男人。肯定会告诉你。到底有哪些个常用的,常用的就这么多几十个而已。parallel常用的参数又有哪些?CMS常用的参数又有哪些G万常用的参数又有哪些?

所以加起来呢也就几十个而已。

不用担心。Okay。脾今天可以放吗?可以啊,没问题呀,脾在哪儿聊聊小姐姐就知道了。好,我们可以继续了吗?可以继续,老师扣一了。😊,好玩啊,我跟你说,实战的东西还是比较简单,又比较好玩的。太多了。

我就给你700个参数里头,我给你摘了几十个出来,还多,你还要怎么你还要怎么着?😡。

好,你看啊程序呢已经开始呃慢慢的呢在不断的产生GC了。由于它不断分配对象,所以它不断的产生GCA。

嗯。

系列 4:P15:【JVM调优实战】用top、jps、jstat、jmap等“业余”命令行工具进行定位 - 马士兵北京中心 - BV1VP411i7E4

好,下面呢我教大家一些。呃,常见常用的命令用来跟踪我们java的进程呢,到底有没有什么毛病和bug。第一个命令。叫做JPS但是同学们你们呢也不用记。

作为老师这么体贴的男人,你猜我给你记下来了吗?一定是记下来了,所以不用挤啊。常用的工具我都给你记下来了嗯。

好吧。好啦。

。好,我们先聊第一个工具,第一个命令叫做JPS这资料可以领啊,没问题啊。第一个工具叫GPSGPS全称的叫java processes。什么意思呢?就给我列出来整个系统里面java的那些进程。

我们java两个进程。第一个就是GPS本身,第二个是11800的T155服,就是我们内程序。就是它好,这是第一个命令。😊,第二个命令是什么?第二个命令是the infer。

你看一眼它的名字叫java的 infer,很容易就能理解这东西是是个啥呢?这东西是java进程的一些相关信息。后面当然要跟我们进程的名称,11800回着。

他会把11800这个进程相关的一些属性全都给你列出来。

啊,比如说separator是什么啊,比如说那个我们的java的虚拟机是谁来提供的啊,等等等等吧,其他的比如说我们的bu class pass里面包包括了哪些站文件。

等等等等吧啊。比如说我们它的嗯默认的这种启动的参数是什么?嗯,com line的参数是什么?OK这一份这个通过这些信息呢,你可以定位一下你你的程序到底哪有问题啊,这两个命令非常简单,我就快速过了。

OK下面呢我来教大家另外一个命令,这命令呢叫J state。This later state the。statistics叫做叫做java的呃统计信息啊,或者叫java的数据的跟踪信息。

this date最常用的,你要跟参数呃。J state的杠GC就是跟踪他的GC的一些信息。后面呢跟11800,这是什么东西呢?跟上我们的进程号。

然后回车哦,你会看到他会把。内存里面的每一块区域占有的大小全部给你列出来。当然这些区域呢,其实它代表的什么意思?上网一搜你就知道。但是这个东西呢读起来呢特别的特别的。不爽不顺啊,这东西读起来特别抽象。

呃,这个命令还有一个参数可以跟后面跟1个500,指的是什么呢?每500个毫秒刷新一次,你能观察到你内存的动态的变化。这命令在不装我们后面我要讲的超级的工具之前,这个东西呢完全是有用的啊。

你可以用它来跟踪你内存的增长过程。你注意看这块内存它会不断的往上增长啊,中间这块。这块儿。从27直到313233,当然你跟踪了之后,你就会知道哦,原来我的程序已经在不断吃内存了。

会产生这样这样的呃一个直观的认识。

好好听我说啊,就是这里面的每一个参每一个名字代表什么,我就不给你解释了。因为后面呢我会教大家在实际当中能够用起来的呃工业级的特别棒的一个工具。阿里开源的阿尔萨斯好吧,OK你知道人民命令就行。

这些命令都是JVM自带的JDK自带,直接拿来用就行。

好,除了这个之外呢,我教大家另外一个命令,这命令是什么呢?Jt。Cl J stack。这也是一个非常重要的命令。这t的意思t叫站。站是谁来拥有来着?还有印象吗?是不是县城啊,县城才会拥有这。

所以Jt就是用来跟踪县城的。11800,他干一件事儿,会把11800里面所有的线程。

所有的见证啊。还木吧。一瓶两瓶三瓶四瓶,你就会看出来它会把所有的县程县城名的线程编号、县程的优先级。操作系统级别的优先级,现成的状态啊,这是现成的状态。包括县城的调用对战。

tack trace就是这个方法掉了哪个方法,这个方法又调了哪个方法,A方法调了B方法,B方法调了C方法啊,调用站,把这个调用站给你打印出来。这有很重要的作用。比如说你观察到某一个县城或者某几个县城。

一直是waiting在某一个所上面啊,这个candation看了吗?就这个线程一直是waiting on condition。如果很多县程一直wa在某一把锁上面。

那么这时候是有可能是说你的你的程序产生了死索。还有。在面试官问问题的时候,有一个经典的问题,这个经典的问题是。同学,如果你的这VMCPU爆了,请你告诉我怎么去。查这个问题。怎么追查这个问题?

如果你的GVMCPU爆了。比如说你这VM。90%的CPU持续。居高不下。怎么查?有谁遇到过这问题吗?面试的时候,面试官问你。有遇到过吗?你看打小打小就遇到过,因为他打小长大的。向死而生。

他遇到的问题比较多。对。top杠HPtop杠HP呢是说你已经知道这个JVM已经占据占据占据比较高的CPU了。他问你呢,是知道你的JVM已经占据很高的CPU,你怎么去查它呢?怎么去定位问题呢?水和牛羊。

毛老师别闹。马老师什么时闹了?马老师作为中国正经老师,number one严肃课程,number one的老师,怎么能闹呢?一般是某个线城在发傻。如果一个线程在发傻,它在wait。

它是不需要消耗CPU的大哥。采样分析,最后是加密算法问题。小杰,前两天咱们联系过是吧?还听我说啊。好,听我说CPU比较高。拿什么看?其实你呢得去查。这个线程它呃就是什么样的线程在占用CPU。

那么这东西怎么查呢?教大家系统级的命令。所谓系统级的命令指的是。听我说所谓系统级的命令。指的是linux系统提供的下一个命令叫top。贵州。当我们一条top回车的时候。

它会给我显示出来当前系统里头的哪个进程占的CPU是多少,占的内存是多少。

如果你top多观察几次的话,你就会发现它的内存会不断增长。它的CPU呢有可能是忽高忽低,这是我们的程序产生的问题。当然,如果你只是观察top这个命令的话,你只能观察到某个进程占的CPU比较高。

如果你想知道这个进程里面哪个县程占的CPU比较高。

小伙伴们,你得用另一个命令,这命令叫top。依然是t,但是杠HP11800回手。

他就会把你这个县程里面的你这个进程里面的所有的线程给你列出来。然后他的CPU。

给列出来。所以如果你要是玩这个的话,得得怎么办呢?啊,得是这么办。得这么干,你仔细听我讲啊,就这块呢如果不采用先进工具的话,你得这么干。首先top找出来哪个进程占CP比较高。

接下来top杠HP找出来这个进程里面哪个县程。占CPU比较高,然后根据这个线程编号,用Jt。对照Jt执行的结果,Jt大家知道会跟踪出来好多好多线程。把这个线程编号跟Jt结果对应上。

看看这个县城到底是哪个。一般来说,我讲到这还能跟上吗?能跟着给老师扣一来,可以吗?good,这块也不难啊,就是一些思路和工具的运用。很简单很简单啊。你放心啊,再难的问题在老师这儿都是很简单的。

so easy。to simple那you在这里。找到这个县城之后,需要定位这个县程有两种情况。第一种情况,这哥们儿是。VMth一般就是GC垃圾回收现程,这哥们是业务现成。那这二话不说。

去看这个业务线程里掉了哪些方法,是哪个方法不断的循环占CPU呢?这就是业务进程,你怎么去查,这跟业务相关。假如你定位到是GC,那么它一定是在频繁的GC。不断的GC,所以它的CPU才不会不断飙高。

这时候就干嘛?读GC的日志。

看看日志里面是不是在频繁DC原因是什么。有可能压力突然间爆表了。双十一正好赶到12点那那那那一秒,哗来了一大波的流量爆表,啊这是正常的,你应该能撑住,撑不住的话,你扩机器。还有一种内存回收来回收去。

总是回收不掉。那么这种情况就是有内存泄露。这过程我说清楚了吗?听明白同学老师扣一来。😊,嗯。good,你看他现在CPU已经占993。9了,看到了吗?😊,好,我们看这里。

当我们看这个呃我们程序的输出的时候,你会发现它已经在不断的FDC了。注意看。最关键的是呢,我们来读它的这个输出信息啊,你看一眼它的输出信息呢会明确的显示出来。这哥们儿呢FDC的过程是这样子的。

他每次的回收内存是从20兆开始回收198015。回收结束之后还占多少内存?198098009就回收了6K。我们总的大小198016。回收一次就回收了6K。哎,这哥们儿还特别的。坚持。他呢也不报啊。

内存也不爆,每次就回收个6K哈哈。嗯。Okay。好,那说明什么?说明我的内存里头一定有一个有人在不断的占内存,而且我回收不掉它。再说一遍。当你看到频繁FGC的时候,这个呢就叫频繁FGC。一秒钟好多次。

或者你内存比较大的时候,几秒钟一次、十几秒一次都可以认为是比较频繁。还要听我讲。频繁FDC怎么定位?这个也是面试官经常会问的。频繁FDC怎么定位观察你频繁FGC的每次回收过程是不是正常。

比如说你这里显示的是从每次都从200兆回收到20兆good,这个是正常好吗?这是 normalmal是正常,没毛病,不要给人家吃药。他频繁的原因,你的前端的压力太大了。他的那个负载太重了,他必须得处理。

这个很正常。但是如果是说像是我这种的,每次200兆回收完还是200兆。那么你想想看它发生了什么问题啊,一定是在我的内存里头。有谁把这内存全给占住,而且呢?都有引用指向。垃圾回收不掉。没有你吧。

听听听懂听懂我的意思了吗?好,我们可以继续吗?可以继续,老师扣以。这小程序牛叉就牛叉在,它呢是不断的产生毛病,它还不报哈哈它偶尔会报,偶尔不报。就是这么的牛程。Clear。我们在把这终于跑起来。

不然我没法定位呢。好的。下面我教大家在这个小程序里面。是由谁在调用,在占用我们内存?谁在占用我们内存呢?教大家另外一个命令,这个命令叫做。Come on bybe。好,这个命令叫做。

Yeah。著名的JmGm呢这个命令有两大作用。第一大作用呢是帮我查一下堆内存里头哪些个对象占用的情况,就是不同的类的对象占用内存的比重。占用的情况,这是第一个。第二个呢叫产生。堆转储文件啥意思呢?

什么叫堆转储文件呢?当你怀疑这个JVM的内存里面有bug的时候。你用这个命令可以让。整个的这块内存。导出来。存到硬盘上存成一个。文件,然后你可以把这文件拿出来分析。大家听明白的意思了吗?来再说一遍。

这面赔两大作用,我一个一个给你演示。我们今天说第一大作用。Gm的离带作用。刚。hiisttogram生成对象图46。我们我们我们得看我们那个进程号是什么啊,GPS您的进程号是12049。sorry。

不是11988。说不定正号jam,你看hi program。跟进成号11988,魏哲。它会生成什么呢?它会当前你在正在运行的这个JVM里面,它会对你进行一个整体的分析。从头儿给你分析到尾。

哪种类型的class里边有多少个对应的对象,我们看脑袋就知道了,看这里。

来注意看。有这种类型的对象,333个。占了这么多字己。有这种类型的对象,什么类型呢?叫stter filter task。还有一个叫big D mode,还有一个叫ca in的。

这是我们刚才读代码的时候读到过它有多少个对象呢?这个类有多少个对象呢?11万个占了多少个字节呢?这么多个字节,然后呢,它是从大到小排列。大家看懂我的意思了。来。当然其实大多数的时候。

我只需要观察前面的部分就行了。爱的取取取前二十行就行了啊,我不需要观察下面这些就只有一个对象的,它一定是占不了多少内存,他不会说让我回收不掉的。回证。好。

从这你就能看到这个呢是目前为止在我们整个的JVM里面最占内存的那些对象就产生了。这是这map的巨大的作用,不知道大家ge到没有。所以同学们,你们想想,有一些东西我回收不掉,我执行完Jm之后做了对比。

比如说就拿这个big decimal的对象来说,big decim对象你的前面是18万个,我又执行一次就变成20万个,没回收啊。来再继续。变成22万个没回收啊。变成哈依然是22万了。23万个。

不知道大家观察到没有?有一些类的对象在不断的产生,而且回收不掉。Yeah。H。Yeah。所以会产生什么问题啊?你是不是get到了?我的内存被占用,回收不掉,就是由这些对象引起的。是。哦,这块还能跟上吗?

能跟上给老师扣一。这是音的数组。叉数组by类型数组这种的一般都比较正常,不会出大毛病。嗯。那这事儿是不是就简单了?既然你知道哦,原来是我的sgattered filter task。

或者是n或者是b decimal,或者更有甚的是cut in。是由这些类的对象不断的产生,而且回收不掉造成的。那怎么办?简单你去查你的业务逻辑嘛,你去查你业务逻辑不就完了吗?很简单啊。😔,查业务逻辑。

好,这作业留给大家吧。我告诉你。我教你定位东西超级简单。

他再难,在老师这儿也是嗯小菜一碟儿,豆芽子长一防高,它也是根菜啊,想咋吃咋吃。但是呢真正在业务环境里面,就算你定位到是由于calin这个类不断产生对象吃内存造成的。可是他原因是什么?你能知道。你试试看。

我的小程序给你,你们自己去调,看看能不能把这bug给调出来。我告诉你,如果你不懂。现成池完蛋,你还是调不出来。就算你懂现城池,你也未必知道问题出在哪儿。更何况在你实际工作环境之中,这些毛病啊。

你的业务逻辑呢是分布在很多特别复杂代码比这个要长好多的那些文件里面。所以,定位问题并不难解决问题才是真正的难。

好,我们稍微的复习一下。

我今天呢给大家讲了几个常用的命令,回顾一下,第个叫top。第二叫top杠HP。

好。第二个呢叫GPS很简单,这infer。

列出信息来。第31个继续啊叫this tag。O,这 state。OK还有一个呢叫jam。 jm的第一个作用,把里面的每一个最用的最多的这些个类给列出来。所以当面试官问你的时候,你就可以说了啊。

我实际当中写了这么一个程序。

风险普查模型,然后它产生了内存的泄露。我们频繁频繁GC,但是回收不掉。后来我一定位,我发现了卡yinfer经过我的努力修正了原程序的bug搞定。听清楚了吗?嗯。来跟上来老师扣个一。

面试官问你谁当中什么情形,你就像我这样噼里啪啦说一遍,搞不定。😊,当然。怎么改怎么改,你自己去自己去找。当然你这么说完呢,估计面试官会一个大嘴巴子抽不上来。告诉我。

你生产环境之中难道可以随便执行Gm命令吗?如果你告诉面试官说我这卖命令是在生产环境之中执行的。面试官估计就是要请你出门右转,拜拜。还为啥嘞?关键是怎么搞定的,哈d森还搁那纠结呢?

怎么搞定的是你的业务逻辑问题。大哥,我今天给你讲的是JVM的调优。你的业务逻辑出的问题,别人能知道吗?只有你自己知道。ok。听我说听我说。这m这命令会产生一个很严重的后果。产生什么后果呢?

我们现在内存啊就200兆,真正运行起来了之后,就中间我开始运行它,估计就占了几十兆的时候,我就开始把它运行了。这m会让整个JVM卡死。卡死在某一个状态,stop the world,然后把里面的。

对象全都输出出来。Very good。真正生产环境能让你卡死吗?大哥懂吗?能不能。你现在双十一正搁那儿秒杀呢,上来一个你Gmap连连连续掉十0遍,哇,卡死10次。关键人家内存还特别大。128G。啥了。

一个Gm命令。2个小时以上。Yeah。所以大哥别这么玩,别这么说。这是一定有问题的。跟面试官聊的时候怎么说呢?我先卖个关子。你听我讲。我先把Gm的另外一个作用讲出来,还能跟上吗?不能强制停止吗?

你看super king多牛,那边双十一正在秒杀呢,直接把电源给拔了牛刀。佩服。你猜马云会不会拿大鞭子抽你?上次不是说半夜执行吗?可以啊,没错。哎,半夜执行是一种说法啊,这个没问题啊。

就是你是在半夜的时候执行的。可是半夜执行,他万一不是FDC特别频繁的,是吧?嗯嗯。😊,总而言之呢,要说的,你要跟面试官聊这些,一定是要聊的。跟实地生产环境要更贴近。3SLB摘下来执行。good不错。

还有一种说法是什么?来的访问复制一份,复制到备份机,在备份机上执行。good不错,测试环境压测的执行,good不错都可以get了吗嗯。好,我们来看第Gm第二个命令,第二个作用。是。啊,看这里。呃。

那么Jm的第二个作用。我先把我的头像投出去。再看这里。嗯,Gm第二个作用是什么呢?第二个作用是它可以用量来写dump。for等B就是banary二进制类型产生一个d部文件。fiile等于。

咱说就今天是2020年9月11号,20200912。There H profile。后缀名无所谓啊,后缀名写什么都行,这是产生一个我们整个堆内存的转储文件,然后呢来对它进行分析啊。

然后后面跟我们的ID号,ID号是什么来着?11988是吧,11988回者。好了,他这时候开始把堆进行转储,产产生完了呃。嗯,这是我们新产生的啊20200912的H法。好,听我说一句。

这个堆专注文件的意思是把java的整个堆整个堆。KVM的整个队导成一个文件。然后下面可以你对这个文件进行分析。对这文件点行分析的时候,就完全可以使用那些网上你们喜闻乐店的各种工具了。比如说。

图形渐变的JVOVM。

。这是Jvi VM嗯,你你你你打开文件啊装入,你就直接把那个刚才那文件呀给它装入进来就可以了。这种的pro给装入进来,好吧,然后呢,装入进来之后呢,你找到内存,找到抽样。

然后你就观察出来到底是哪些个呃对象啊占的内存比较多,你就观察出来了。

嗯,这是一种,好吧。这是第一种。

系列 4:P16:【JVM调优实战】用图形化工具visual VM、MAT、jprofiler进行定位 - 马士兵北京中心 - BV1VP411i7E4

同学说了,老师这个JBVM我没接触过,这是java自带的这东西这东西用我说吗?这东西我说吧,不用吧嗯。不用不用啊,很很很简单啊,这是javaJDK自带的。好吧,说两句。有同学实在是基础太弱。

你基础这么弱,我就没招了,简单跟你说两句吧,你你就是你java装完了之后。😡,JDK battery里面,你找到J。viro VM就是这个图形界面的工具。这通文界面的工具呢它也比较强大。

它呢除了可以观察你本机的这些ID之外,也可以装入用文件来观察,也可以干嘛呢?也可以远程来观察啊。比如说这是你linux服务器,你也可以用1个JBra远程连接去观察它。

这也是可以的,这也没问题。嗯。然后你就可以对它进行分析了。分析完之后,你也得出结论了。原来是card infer那个类太多了,依然是这个结论,没有什么其他的。好吧,然后下一步查你业务逻辑,查业务逻辑。

别人就替不了你了。好,这块内容讲的稍微快乐一些,来能跟上一老师扣个一。因为觉得这个比较简单嗯。没问题吧,但是。但是。我讲这么快是有原因的,因为实际生产环境之中很少这么玩儿。原因是啥?

你往外导文件依然会产生卡死。会让JVM卡死,你能让你随便倒吗?不能。所以这就涉及到你什么时候才能把这个文件给拿到。生产环境里头的第一件事儿,好好听我讲,生产环境第一件事儿叫做。设置好你的启动参数。

这个启动参数啊。

包括这个参数。hiap, dump on out of memory error。就是当我们启动的时候,一定要把这个参数给设置好。这个设置好的意思是什么呢?就是黑 down。什么时候产生OOM了。

什么时候它会帮我自动生成堆转储文件。再说一遍。什么时候你的内存爆了?它会自动帮你生成一个对专出文件,d文件。这时候你内存爆了,你相当于你java进程已经死了,这时候就没关系了,把你这文件拿拿出来做分析。

分析的工具特别多。我呢跟跟大家说过JVMJDK自带的Jhead居命航呢。ecclipse带的MAT完全也可以,还有其他各种各样的工具都可以。刚才有同学提到这些 easy,那是读日志的。

跟这没有半完全关系。好了,同学们。这块不知道我说清楚没有。所以你在生产环境之中,你说我用Jm导的不对,这个事儿不对,这是第一个。第二个,你跟面试官聊的时候说我远程是linux。我用JVM远程连接上去。

这事儿对吗?能这么说吗?告诉我一下。这c也可以远程连接。这比如VM也可以远程连接这proeller收费的也可以远程连接。

来,你要跟面试官说,你说我在生产环境之中,双十一那机器正在那玩着呢,我上1个JBUVM去观察它。

完蛋。面试官估计一个大嘴巴子抽上来。那凉快哪带着你搁哪学的吧,你。出门又冷啊,拜拜。听我说一句。在生产环境中的机器一般情况下,除了运维之外。尽量不多开任何端口。但是你如果用远程的这种图形界面去连接它。

sorry必须得开各种各样端口,产生各种各样安全问题。另外呢它会对性能造成一定的影响,大概性能会下降10%到15%。因为他需要不断的对vi这vi VM往外传我每一个对象的状态。好吧。学率是不行的。还。

有同学说了,老师,那我人家面试官问我,我是怎么查出来的呀,我该怎么办呢?好,听我说一句,如果说你说是图形裂面的工具观察出来的也可以。什么情况,比较牛逼的说法是。我是在压测环境里头压测的时候。好。

挂一个上去远程观察,这个没问题,这是第一种说法。第二种说法是我们机器做了负载均衡。我们发现程序有问题之后我。把这台摘出来,从负载环境里头摘出来,我把它的堆转储文件导出来。好,这个也没问题。

very good。这是第二种。第三种。由于双十一的或者是什么样的这些个从互联网过来的连接特别多,我用TCPd这个命令给他复制一份。一份儿打到我们的生产环境里头,一份儿打到我们测试环境里头。

我们用测试在测试机上做观察,good牛逼。说明你不仅懂负载均衡,你还懂TCP蛋吗?你还懂生产环境里头这么调优的手段。好了,50万给你了,公开呢。呃,我说清楚了吗?TCP不sorry TCP copy吧。

TCP copysorry啊,不是不是TCP done。I'm sorry嗯。super king这是50万必备的技能之一。反正不是你那摁电源,好吧,super king,你要摁电门那个那别说50万了。

5000多千多。super king啊。好嘞,我们可以继续了吗?😊,嗯。Cl。

但是呢在这儿我今天给大家介绍的并不是这个。

系列 4:P17:【JVM调优实战】用一线大厂专业工具:Arthas进行定位于调优 - 马士兵北京中心 - BV1VP411i7E4

要的呢是阿里开源的工具,这工具很有名,目前用的特别多,这工具名字叫做阿尔萨斯。叫SS好听我讲啊,作为ass来说是阿里开源的中文文档的工具。今天呢我带大家用一下,但是我不想带大家安装了。这个没问题吧。

我不想带大家安装了。安装你自己去玩,我要他跟着讲安装就没劲了。好,作为阿尔萨斯来说。下载下来之后,解压解开之后得到这个目录,进到这个目录里去。

我已经进来了。想执行它的时候,执行这个栈文件就可以。它有好多种启动方式,这是最简单的。加个壮这。Others gone。当它启动之后,它会自动的寻找你当前机器里面的。那些个java的进程。

目前呢只有119988号进程,在它的阿尔萨斯的内部编号里头叫做一。所以你挑一。阿尔萨斯尝试着把自己挂到这个进程上。可能挂不上去了,因为他已经死了。重新器啊。挂不上去了,稍等。卡屏了吗?卡屏了吗?

我还在吗?我还活着吗?你们还在吗?你们还活着吗?Y, but。重新启动,我们重新挂一下。啊,O。重新启动了小程序,我们在阿尔萨斯里面挂上它。回咯。当你看到。

这个输出的时候说明2尔3斯已经正常的灌到了我们这个进程上。这进程号呢是12202。这块能跟上吧,就是在我们整个系统里头,这是一java进程。234的进程在这里,234挂到这个进程上,然后对它进行观察。

好啦。可继续吗?下面我来介绍。阿尔萨斯它的一些个功能,这个不会STW这个性能上会有所降低,但降的不多。至于会不会STW大哥取决于你要执行什么命令,阿尔萨斯完全可以替代我前面敲的。

基本上能替代我们敲的所有命令。而且他比较直观。打开榴览。234。他有好多命令,如果你不知道的话,你就叫help就好了。

Help。嗯。他有这么多命令,help key map ICSMclass loader JADt等等等等等等等等,乱七八糟的。好了,同学们。

在这些命令里面,我教大家几个,一个呢叫dashboard,这是最常用最简单的一个命令。dashboard仪表盘回车。

它用命令行底下模拟一个仪表盘,在这里面,它基本上综合了top那个命令和top杠HP命令以及这infer命令的一个组合。在这你能看到你的整个进程里面有哪些个线程,有哪些线程在吃CPU。

现城吃CPU的都都放在最前面嗯。然后现成的状态是什么?接下来内存占了多大,一电区占多少,swiber占多少,老年的占了多少,非堆内存占多少。ok好,这些都是常用的一些参数的信息。啊。

所以这个一个dashboard搞定了,很直观。最关键的最最好用的是这个就是到底哪个线程在吃内存啊,吃CPU你如果用Jt和top杠HP组合的话,你得来回的换算。因为他哥俩呀一个是十0进制,一个16进制。

我跟你说,这哥俩你得来回换算,但是你若果用二萨斯的话,直接一观察就知道了。哦。原来是52号县城,他的现程名字叫pro1339,他在吃CPU,不知道大家听清楚没有嗯。好,这是第一个命令。

我们继续除了这个命令之外,还有一些什么命令呢?

Help。看这个命令,hiep dump还用我解释吗?这边就没有一点是吧,hiep dump替代谁的?替待哪个命令的能告诉我Gm是吧?这太简单了啊。Heep dumpok嗯这 map对。哦。

还有一个命令叫thread。

回州。他会把整个你的进程里面所有的线程全给你列出来,哪个县程吃CPU最多。

最关键这个工具有一个特别牛叉的地方,thread你小杠hel。

呃,第一个呢它的帮助非常的给力啊,你完全也有中文版,这这虽然这是英文版啊,但它是完全有中文版。另外呢它有好多好多的这些个examples,你都可以直接拿来用就行了。特别简单。

来教大家thread里面最常用的一个参数,这个参数叫杠B,看一眼这什么意思,读一下。😊,thhreadagon include blocking thread啥意思 Find thread who is holding a log that blocks the most number of threads。

啥意思?对,查找死锁查找死锁。你像我教你用Jt的时候,你还记得吗?Jt。如果你要观察死锁的话,你得去观察每一个线程它是不是wa在同一把锁上。喂了好长时间,这个时候有可能会产生思索你也会检查。

但是在阿尔法斯里面一个命令就可以搞定了,直接敲。出来关闭。当然我由于我们这个线程呢,我们这个程序它没有思索,所以它找不出来numbous呃bling three found。

如果是你自己故意写一个思索程序,你用这个来观察一下,一把就给你找出来。好用。点赞。可以继续吗?嗯。How are you meeting叫 JVM JVM。当然这个命令呢其实很简单。

它就是那个J infer差不多,它会把这个java的进程,一些常见的参数。

是怎么设的,给你列出来哈哈。这里面有一个比较好玩的呢,你可以观察它的garbage collectors,就是它默认用的哪种垃圾回收器呢?Gbage glers,但你会你会发现年轻的用的是copy。

老年的用的是mark sweep compact。一般mwe啊mwe到一定程度碎片化了,compact进行压缩。

好,还有其他命令吗?还有。教几个比较酷的这就个太简单了,交几个比较酷的。

来我们来看这个命令。可以跟上吗?新时代说抽奖吧,不抽,不要带节奏。再节奏,我先把你的名字给踢出去,我再抽掉。为啥这工具不会影响系统性能?大哥,我我哪句话说不会影响系统性能啊,我说过吗?

这个会影响系统性能10%到15%。好,看这里。看这里教大家这个命令,这个命令叫JAD。okK这里的意思是什么呢?嗯。

就来这个命令的话呢,我就换一个程序吧,不用这个程序了。我们换一个小程序。Clear。在这我还有小程序啊,这小程序呢叫。叫T我们先来看这小程序啊。

Yeah。moreT点回好,看这里啊,这个小程序,我这个T这个小程序呢是干了这么一件事儿,你读一下啊,很简单,三贝函数里面写一个死循环,这个死循环s andread我从呃命令行上读一个字符进来啊。

读一次,我就扭出一个TT对象来调它的M方法。

MoreTT点点了。comTTTTM方芳怎么写的?这方法超级简单就是sem点2的pre line1。就打了个一,所以你执行这个程序执行起来,这是这样子的javaT回车。😊,输一个字符。

他要出出一个一输一个字符,出一个一输个字符,出个一输个字符出个一。嗯,这个输了三个字符,所以出了三个亿。好的小程序能看懂吗?😊,相当简单。下面呢我们通过阿尔萨斯挂上它。

Yeah。教大家一个命令就是JADJAD的意思是反编译叫jeva decomp反编译javaJADT这好,你就会看到哎他把。整个呃源代码呢给你反编译了出来。然后JDTTTT。回者啊在线反编译啊。

给你反编译出来。有同学在这就开始说了,老师,你逗我玩呢,这破工具能有啥用啊?我代码是我自己写的,我还用反编译,我不是有毛病吗?来认为这个工具没用的,给老师扣2,认为有用的给老师扣1。Yeah。

有扣2的吗?没有吗?嗯,还有的时说太有用了,还有科尔的说没有用。😊,来凡是扣2的。我估计你们就是在小P公司里,一个小P工程师拧着一个小P螺丝。为啥呢?其实啊。在一个超级大型的项目里头。是有很多个团队。

共同。把代码往上写A团队的代码有可能依赖B团队。B团队一个成序员把整个程序上运行起来之后,发现代码怎么不对呀,我检查我自己代码也没问题呀,为什么输出结果是不对的呢?本来这里想输出的是2。

结果你问您老人家为什么输出的是一呢?好,我领你听我讲,你这时候怎么查呀?哈。这个时候你如果怀疑有可能A团队用错了B团队的版本。版本听懂了吗?很有可能是A团队用错了B团队的这个版本。

我的第一个版本里面输出的是2,第二个版本输出的是一,结果你用错版本了,你输出的不对,并不是我B团队的问题。我怎么定位这个问题啊?没办法,在线反编译。对,先开始开始扯皮啊两个。两个那个那个哎。

为什么我这图像这么模糊啊?关闭摄像头,重新打开。哎,为什么那么模糊呢?有点模糊啊,大家凑合看吧嗯。对,两两个小组的组长,A组和B组开始扯皮,看看谁嗓门大。互相猜忌,然后论证。

这时候呢其实很简单去上线反编译一下,看看正在运行的是哪个版本就搞定了。建筑清凉,长得模糊。对你是怎么知道的?我用了好多锐华技术才达到这种情形,混淆过代码可以反编译吗?反编译,不管你什么代码。

当然可以反编译,只不过混淆之后,它反编译出来是那个混淆的那份代码。好了,不知道这个问题大家听清楚了吗?在线定位一些问题,bug到底出在哪儿啊?这个反编译工具很重要,很有用。JAD是哪个命令?

exception的名字是哪个?哎呦,我的妈呀,JAD是哪个命令,你还要问我这AD命令那就是JAD了。大哥。嗯。那。idea自带反面译来super kingsuper king提出的问题总是能触及灵魂。

super king的意思是说,当你这个程序在远程你的服务器上运行的时候,它可以用idea远程连上去给你反编译下来。哎呀,super king,你赶紧你这个骚操作,如果能做出来,赶紧教我一下啊。😡。

佩服啊,简直。实在是太佩服了啊。哇。Okay。😀呵呵。😊,Yeah。嗯。😊,可以用javaP。好,可以可以可以,完全可以嗯。好吧好吧好吧,你你你们别搁这扯了啊。

那个凡是提出奇奇怪怪的问题的那些啊奇奇怪的知识,奇怪的问题啊,奇怪的问话你就不要再提了,好好反思你自己,你就是那个小P公司的小皮螺丝钉,记着这个就行了啊。😊,好嘞。来,我们继续。

那现在下面我再讲另外一个比较酷的比较酷的这样的一个命令。这个命令呢叫reefine。Reefine。好,reading fun是什么意思?define define是定义。

如果你学过老师讲的class load,你就应该知道这个东西呢是定义一个class用的,是可以修改一个class的。reeffin叫在线修改class。啥意思呢?仔细看,现在这个小程序当每一敲回车。

它输出一,一敲回车输出一。但是经过定位你用错版本了,我不应该输出一,而应该输出的是2。那么这时候怎么办呢?一个骚操作是这样子的。注意看。我不要把程序停掉。你继续运行。我干这么一件事儿。我干这么一件事儿。

V。继1点亮啊。我把这里的一。直接给改成2。存单退出。然后呢,加个CTT。等着把它编译好,把这class上传到远程去。这是我本地上传到远程嗯。接下来在阿尔萨斯里面,reefine。root下面的。

T P their class。没说。好,ready翻成功之后。直接在原来程序上回车,哎,已经变成二了。嗯。😊,这又是一个骚操作。当然有同学可能就会说,老师这破东西有用吗?我难道就不能本地代码改好了。

把一改成二编译好了,把原来的程序覆盖掉就行了吗?原来程序停掉,等我改好了,覆盖,然后不就搞定了吗?对不对?你没事在线改,你不是有病吗?来认为有用的,老师扣一,认为没用的扣2。Yeah。

那又有人说可太有用了,是吧?嗯,李晨嗯李晨扣2扣2的不多,特别有用是吧嗯。你们跟担心这种权限问题的那是人家运维的权限的管理,跟这有半毛钱关系吗?担心的问题都不知道担心在哪儿。这边你跟你媳妇儿结婚呢。

你担心呀那个美国那边要大地震着火了,你这不扯呢吗?😊,对,在线改单码。这个呢最关键的点呢叫不用重启你的在线程序,听懂了吗?因为什么呢?如果说敲12的,您您还是那个小P公司的小P螺丝钉,为啥?

大企业做项目做在线项目。我就问你这在线项目能随便停吗?随便说哦,我这有一bug来把它停掉。😡,等我修改完了之后,传上去,发现产生了新的bug,没回事,停掉。😡,穿上去能这样干吗?大哥。

你知道在一个大兴的公司里头,咱们不说大兴互联网公司的,说银行吧。银行一个系统上线。上线之后启动开始服务,经过多少多长时间的,多长时间的审批,有没有在银行的?有没有?挺好发公告的对啊。一周两周很正常吧。

就是你一个新系统上线的审批过程很可能就要一周两周。长则一周两周,短则一天两天,就为了修改你一个特别小的bug,你得把这些东西全部停掉。如果是大bug灰度恢复原系统。如果是小bug,直接在线先把它改了。

双十一马上到了一个小时之后,秒杀开始了。你的这个价格原来是100,你不小心写成了1000,你怎么改啊,能停掉吗?没关系,直接在线先把它改过来,等下一个版本升级的时候,整个bug全部覆盖成新的。

这就是救命用的紧急救命用。嗯,好了。😔,集群用脚本批量执行提款。对啊,你集群只能用脚本啊。没错嗯。一般这是救命用的,并不是特殊的情况下,它特别有用,好吧。好。这个是阿尔萨斯的骚操作之二。

还有一些其他的骚操作,你想看吗?比如说我前面讲过的,你怎么定位一个系统的系统瓶颈呢?阿尔萨斯是可以的。平静。平静哎,静还写错了。一会儿教你234的下一个操操作,好吧,你看殷传宁啊。

我就知道有人得得有人问这个问题,炸包情况下怎么操作呢?😊,哎呦,我的银传宁啊我的银传宁。你你你先拿大腿给我想想这班操作怎么操作,其他同学也帮他解答一下。纸箱炸包里,哎呦我的妖娆尾遂,你赶紧嫁给银传宁。

你们夫妻两个叫做对眼水平一致嗯。大哥,我就想问你啊,各位小伙伴们,在JVM的内存里有炸包这件事情吗?有没有?有没有一个炸包在JVM内存里?炸包是干嘛的?里边装了好多class放在硬盘上。

JVM启动的时候,从这个炸包里面解压,把这class漏到内存。JVM管你里边有没有什么炸包啊?对你咋不说wall包呢?没错啊,你咋不说zip呢?你咋不说IR呢?

你看super king问了个突吉灵问的问题,super king问的问题一般的水平都比较高啊,super king什么呢?VIP中屁,只要他说话,所有人都够停止。认真看100台服务器怎么改呀。

不能一个一个改吧。😊,怎么改?写个脚本呗,写个脚本批量改呗。Good嗯。好的。Yeah。好啦。呃。好了,我们继续来看。另外一个是操作。这骚操作呢我重新启一小程序啊,觉得这小程序忘了。

有点这小程序叫ABC吧,我记得ABC点粘了。Mn, AC or。先读一下啊。Clear。More。ABC年了。来读一下小程序,很简单,看能不能读懂。

看一眼。十几秒钟读一下。是。好这小程序干了件什么事儿?扭了就在for循环里面ma方法里面扭了1个ABC点点A。掉6了ABC调它的A方法。这A方法呢是睡了一秒钟之后,掉了B方法。B方法睡了2秒钟之后。

掉了C方法,C方法睡了3秒钟,很很简单啊。好听我讲啊,就这东西呢呃我主要是模拟每一个方法的调用站。就是这里面你一定知道A是调用了B。B调用了C,然后我用sleep模拟的是什么?

sleep模拟的是我业务逻辑在里面执行了多长时间。大家应该知道,作为一个系统来说。有的时候呢你会观察到你的系统显应速度特别慢。这种的呢我在呃我们的学员里头呢已经遇见过好多次了。

他说老师我这个系统的显应速度特别慢,并发量特别低。比方说这个并发量,你你做一个压测,访问我的A方法,发现我设计是要达到1万的。QPS。好,但实际当中呢我只能达到100。原因是啥?原因很简单。

一定是A方法执行速度特别慢嘛。本来设计之中是10毫秒完成,结果你500毫秒完成一次,你一秒钟也就执行个20次。啊,听你听懂我意思了吗?同学们。这块儿大概知道什么什么意思吧。OK。就说我们要查的时候。

我们我们我们不知道这个系统的性能点到底个瓶颈在哪儿呢?是A呢还是B呢,还是C呢?这个调用站有可能非常长,C又掉了D丢又掉了FF又掉了E等等。这个调用站可能特别长。这个链路上。

整个这条链路上到底是哪个方法出问题了呢?OK234可以帮我们干这件事儿。

好,这个过程我说清楚了吗?可以继续的给老师扣个一来。是。嗯。嗯。true boy,你看人家是真正的男孩,他说链路追踪,这叫单机版的链路追踪。单机版的就是你在这一个JVM内部里面A掉了BB的掉了C。

但是如果是微服务版的呢?这个服务调用了另外一台机上的另外一个服务,他又调了其他的服务,他又调了别的服务。好,这个叫做。分布式链路追踪。今天我给大家讲的是单机版的阿尔萨斯就可以。

这个呢如果你要用分布联路运动zip can。skywalk都可以,好吧,觉得咱们。VIP课里全都有嗯。好听讲阿尔塞斯就可以。当然这种工具特别多,除了阿尔萨斯之外呢,好多好多其他工具都可以用。

比如说Jpror。Profir。当然DDK自带的还有一个命令,我忘了叫什么了,其实也可以呃,命令很多,但是阿尔萨斯的很好用。这个东西是收费的,这pro是收费的GDK自带的呢相对于阿尔萨斯的难用。

所以我讲阿尔萨斯这个版本。好吧。好,看这里。厚德载物。厚德载物,不要停啊。你居然你居然说的是名字,是我们的学校的校训。赵道清华的校训是什么?自强不息,厚德载物是吧?听蛙的小哥是什么?清国的校训是什么?

忘了啊。你们知道北大的。孝哥是什么?校训是什么?小辉是什吗?没有啊,北大的全没有,所以北大又称三无学校。北大每年那个都探讨说,我们距离国际双一流学校到理还差到底还差多远?一般情况下呢,我们都会告诉他。

出你们东门左转100米就到了。就差100米。嗯。😊,北大家就是这么一个牛逼的学校啊。开个玩笑啊,我们继续我们来我们来来来来追踪整个呃这个链路到底哪出了问题。😊,该怎么追踪呢?我们先把它跑起来。じは。

It say。依然是挂上阿尔萨斯。关上234。二回ろ。好,这次我们的命令。是什么呢?是这个证明论的叫tracetrace的意思叫trace the execution time of specified method navigation。

看一眼。这啥意思啊?trace这个。

每这个方法的执行时间嘛。嗯。Thoose。

Help。呃,来看看它的例子程序就知道了啊,trace这个类名哎,然后方法名啊来trace一下。Ts。呃,ABC。方表名是A回着。然后他就开始trace这个方法。

I fed a class count 1, Me count 1 cost in。

这是他方法的分析过程,看到了吗?

他分析出来了,他说呃他分析了好几次,他说你看那个我执行A的时候,我执行了6秒钟,我的脑大爷哇,你会发现哇,不会吧,我A设计的是500毫秒,你居然给我执行出6秒钟出来,什么情况哦,他给你定位。

他说原来A调用了B,在B里面。😊,在A里面,自己睡了一秒钟,给你跟踪出来了。在B里面呢,居然执行了5秒钟,我的我的娘啊,所以B一定是有问题的。这能看懂吗?能看懂的给老师扣1。Yeah。

那既然您老人家B是有问题的,咋办啊?追B嘛,看看B是啥情况,怎么回事,怎么执行这么长时间?😡,好,B追踪出来了,说B总共花了5秒,他自己执行的时间是2秒钟,sleep了2秒。但是呢他掉了C。

你会发现C直行了3秒,我勒个去,C怎么回事?😡,C一定一定是有问题的。所以跟到C里面去。嗯,然后来看看,当然你一路追踪下来,你就会发现你这条链路上到底哪个方法,它的执行过程花费的时间太多了。剑走清灵啊。

前几天刚调是吧?嗯,剑走清灵不错。super king啊,这功众号哇,遭到了super king的表扬啊,今天晚上没白讲。VIP有这些吗?必须有大哥,我公开课都有的VIP必须有。对。而且比这详细。好了。

同学们。依有去有有有饮。我们呃呃呃今天差不多就介绍到这里吧,我们稍微回顾一下啊,今天讲的东西呢其实比昨天稍微的容易,为什么?因为今天都是实战,实战比较好玩儿。又有力的程序又能观察到结果。

昨天讲的全是理论,理论性的东西特别难。VIP啥时候开的,一直在开呀。嗯。10点钟我们开始秒杀啊,我们有一个秒杀,秒杀的是我们的自己的课程。

这课程呢我稍微给大家做一点小小的介绍。呃,这课程我们目前叫MCA。他叫什么名字不重要。关于这个课程呢,我稍微如果想了解我们整体课程的话,我得给你简要介绍介绍我们的历史。

听着玩吧。老师给你讲历史也是很好玩的。我们是这样的啊,我们大概在呃19年的中旬啊,19年6月份开的第一次课,在腾讯课堂做在线课程。我们大概用了半年时间就达到了Java类目的第一名。

那个时候是提供8个月左右的知识课,每每周三次课,每次2小时啊,跟别人是一模一样。后来呢。我们呃跑着跑着,突然间发现呢,就是那会儿那会儿我们可程也便宜啊,大概六七千块钱。好,我们跑着跑着呢。

突然间发现呢这8个月时间根本不够。因为我要讲的东西特别多。讲的又比较深入。每一个课呢我都想讲的特别深入,深入到原码层级,深入到实际过程之中到底是怎么用的。所以发现时长不够了怎么办?

我们后来呢就把这个8个月课程直接免费的扩展到124个月24个月左右的课。这个加起来的话呢。而且每周不再是三次课啊,每周是一堆课。每周不再是三次课,每每周大概是大概是这么多课。这这这还是少的。

嗯看上一周的话,它就会更多啊。如果再看上一周的话呢,他会他他会更多啊,都是一堆课就不再是三次。就是我们课程量大增,把课程拉的特别长。然后呢,只有做的特别特别时长够啊,特别特别长才能讲的比较深入。

只有特别长才能比较深。这个很正常,时长不够,我不太可能能能够能能够能够想说你能讲的特别深,这不可能。就像课堂上有些抄我们的是吧?啊,说自己的时长也2000个小时,然后每周就讲6个小时,你自己算一下。

大概有300周5年左右,你不扯了吗?啊,基本讲课就一个老师,别这样啊,这么抄你骗傻子呢?好,看这里啊。呃,这是第一次的拓展。后来拓展完这个课程的这些个知识点之后啊。

这是这是这是我们呃最开始做课的时候的那些知识点这样子的。那会儿呢我们叫高成客。嗯。对。Yeah。那会儿叫高层体系啊,叫高层知识体系。这这你可以认为这是去年提供的呃这些个课程。呃。

像我今天给大家讲的JVM呀,这个GMM呀、多线程啊等等这些这都是呃呃就是我们原来叫那个高层的课,当然还有设计模式呀,反正你能想到的这些个知识点的课啊,基本上全有。呃,一直到分布式的。

到那个MQ的到keeper的到原码的解读的到那个RPC的到spring bootsp cloudcker云计算的my调FS open以及团队化团队管理的。

一直到我们的这个大数据相关的一直到流式计算f stream源码到机器学习的入门成员的数学继算法和学习实战一到呢软技能英语课职业规划指导面试软技巧以及编写技术文档等等。这是去年我们提供的课。

后来我们提供这个课之后呢,发现这课还不够使,你知道吗?为什么?因为每个人啊他的需求是不一样的。有的有的有的小伙伴就跟我们说,说,老师你这课不够啊。我说不够在什么地方呢?他说老师。

我原来是做CROD没有互联网相关的项目。我想在我的简历里头写项目怎么办?我们一合计来扩。扩充项目到现在为止,我们大概扩了8到9个可以写在简历里的真实项目。嗯,这个项目呢是在这个位置。我们项目呢大概是有。

这么多个。呃,从。网游服务器呃一直到这个合家云的平台。到微妙商城到网易车,到一级流量啊,到推荐系统,到流入平台,到中台到秒杀。大概给大家呢专门做了几个这样的项目。呃,这里面如果大家想了解项目的话啊。

你像这个这个课的话呢,已经讲到第三版了。每年我们也在不断的更新它。呃,30堂课才讲完了一个项目,这个项目呢就非常方便的让你从原来的CRUD直接转向互联网分布式微服务项目。而这项目讲起来也特别好玩啊。

我们讲项目跟其他的地儿呢还不是特别一样。可以这么说啊,这基本上从项目到到到到所有的地儿啊基本上全不一样。老师也不一样,老师都是一线大厂出来的,一线大厂刚刚离开的。鲜活热辣的一线大厂背景。像这种项目。

我们是怎么讲的?我们呃。架构啊。源代码二三十个人源代码全都给到你。而且现在这个项目线上是可以跑的。哎,我忘了你跑的网址是什么了。嗯,我头我问问曹老师,给你们演示一下。

你可以你你们现在可以在线上打我们自己的这个车,知道吗?马世平教育的车你可以打,嗯,就像你打滴滴一样呃。😊,而这项目讲解过程是从那个项目立项开始到评审。到架构设计到接口,到工程到DB到开发编码。

开发编码会给你讲到微分布式微服务每一个模块的原理和原码到底怎么运用的。讲到分布锁分布事务,怎么做测试,怎么做部署。最牛叉的是呢,假如说你你这项目写到简历里,人家面试官问你,你说老师我还不知道怎么回答。

曹老师说,他自己帮你去面试。然后把。整个过程面试官怎么问的,给你录制下来,回放给你。这就是著名的保姆式服务,一对一保姆式服务。够牛吧。诚意满满。做到这个程度,你说我还不行呢,这就太少了。这么说。

来咱们这学课程叫做你只要把人带过来,老师让你学啥,你学啥剩下的一切的一切,怎么写简历,怎么改简历,怎么跟面试官聊,怎么谈薪资,怎么建HR怎么建技术总监。好,这些所有的问题全部交给老师。

几个offer不知道怎么选来找老师。因为这20位来自于一线大厂的老师,每一个你都能直接联系,这就是鲜活的你的指导教师,你的导师。我们是导师制一线达肠导师制。你就是头猪。这帮人也能带你飞起来,好吧。

当然一般情况下,你不是猪啊。啊,这是增加的一些新的项目,我就不给你一一一一写了。这是。O。增加完项目之后呢,我们的发展历程呢,当然这个程序这个这个这个就比较长了啊,呃课时已经比较长了,对不对?

各是一秒长。然后我们接下来又进行了一次升级。好,这次升级为什么升呢?是因为啊你学到前面我讲的这些个基数点加项目之后,你基本上差不多是能够达到P6P7水平。但是你如果想拿到一个真正的架构师的资格。

这种的薪水啊大概在差不多顶头顶头在七八十万左右。如果想拿到一个更好的薪水,就是说你这个这个就涵盖你从从进阶啊,P5P6P7差不多拿到一个七八十万的薪水最高的。但有人不满意,有人人家本来就赚七八十万。

想在课程里头再收回一些东西。我们又升级了一本架构课。如果各位在互联网上了解过加构课的话,我相信你应该知道。大多数的架构课叫做PPT架构式。PPT架构式就像这样的架构式。就是哎我给你,我告诉你啊。

一个高可用的架构,高并发的高扩展的架构怎么玩了?前面有防火墙,这里有NX啊,这里有负载均衡,这里有MQ啊,这里有K8S的集群,这里有CSCD这里有大数据等等。你看完之后觉得很嗨。真正让你一操作。

你一个都答不起来。见过这种课吗?见过雷老师扣个一来。😊,Yeah。好,这口还贼贵。我就告诉你啊,市面上凡是架构时刻,我们全报了一遍。就想知道为什么这么贵,然后有能得到的能得到的效果是什么。

后来我们发现我的个去,没有一个能落地的。这种东西呢远远不符合我们老师的脾气。我认为能落地的架构师才是真正的架构师。所以我们的架构师课程。除了这十几篇理论知识之外。最重要的一篇在这儿。这篇东西叫做。

再造淘宝。落地,把理论全部落地。我们这个再到淘宝的过程。给你从实际当中一点点的几十台服务器,几百个节点给你搭起来。嗯,就是你看到的这张图是怎么一步一步。干成这样了。我是一个鲜活的过程,让你能看得到。

而且在我们的私有云上。你可以亲手搭建起来。好吧,这个才是真正牛逼的架构师。你自己开发完整个业务逻辑,代码开发完再亲手把它搭起来。好,这叫架构式,这是马士兵教育的架构师。

全称叫MCA叫马士兵 certifiedtified architect。我们从分布式ID生中心开始搭到配置中心索集群、事务集群。

缓存集群网关集群注册中心监控MQES分布任务调度tenending以及myxico的服务集群。这些我们大概买了服务器,前后花了60万。加上我们私有云的环境搭建,100万以上。

为了讲一门好课。这里叫做不惜代价。

不知道大家能不能 get到这个苦心,好吧。呃,能盖到的老师扣个一。没人干这事儿,除了我们真的没人干这事儿,好吧。嗯。这是我们又一次升级。呃,就这样,所以诞生了我们现在这个课啊。

现在呢整体性的这个课叫做MCA。呃,腾讯呢是这样的,原来一直逼我们把课程给分开啊,分成PP5P6P7P8,你都给我分开大数据啊,我们没分没分的原因是什么?因为在我看来,一个牛逼的架构师。

他要掌握的机知知识实在是太多了。我希望呢在一个课里头全一课全包全都给到你。不要分那么多,从最基础的理论我就不给你一一展开了。因为每一个展开优又特别多。理论基础CAP。到呃比方说这个这个呃密等啊。

到高考用怎么设计,到高高呃高扩展怎么设,高性能怎么设计等等。脑练你该怎么解决?到技术底层的支撑。记住底层啊,像这节课可能链接都已经是现现成的,你直接拿来看就可以,好吧。

从lin内核一直讲到我们存储系统操作系统。Tow。算法。关于算法这块也是特别大的一张。很多很多人他的基础很不牢靠。有很多人认为我去面试架构时,是不是就问我那些个。上层的知识真心的不是那么回事啊。

我就直接告诉你,想面试架构试很多时候问的就是底层。左成云左老师从最基本的算法从最基本的数据结构一直讲到刷题BATword的刷题。这个课左老师在原来的时候要卖6000多。在咱们这儿就包含了整体包含。

分布式算法的支撑,派克索斯一直到。我们这种嗯机器学习算法,因为主要要做推荐系统。到网络基础设施该怎么玩,偏一点运维,但是牛逼的架构是应该掌握到总体设计怎么设计啊,这就太多了,我就不给你一一看了。

就是从单机一步一步是怎么发展到那么复杂的几台架构的。我把这过程给你演示出来,你就理解了,知道吧?因为很多人呢他学不会东西,他是没有看到这个从零到一的这个过程。我把从单机版给你慢慢拆。

服务微微服务开始拆啊,这个数据库开始拆,缓存开始建进建起来等等。一步一步建完了,你就知道哦,怎么从单机版发展到了这么几台机器这么一个对外提供的服务。核心微服务怎么设定?

spring cloud全站又该怎玩?我去太多了。st跑哪去了?啊,这个。有太多了啊,我就不给你打开了,太多了。Yeah。好,然后大数据相关的怎么玩?人工智能建立在大数据的基础之上,我们进行推荐系统。

这个怎么玩?CICD怎么玩?就是我们呃这种服务质量的保着保障性能测试、功能测试,全链路的压测又该怎么玩?运维这个方向该怎么玩?我们技术的前沿性的课程,课题又该怎么去进行探讨?这是我们整体性的课程。

除了包含整体性架构师课,也包含我们的高层体系,包含我们所有项目,整个课全称。啱四。适合什么参加工作的小伙伴们,就是你至少知道SSM你就可以学这个课。有同学说老师,我连SSM都不知道,没关系。

我们有一个零基础的A课程。这个是从零基础的,先把这课学了再学也可以。

这课呢你来。当然我讲到这儿,有同学可能他就会嗯心里打鼓,说,老师我靠这课程太多了,我怎么学得过来啊?好,听我讲,我们课程叫做。4叫做一对一定制。这课呢不要求你学完,你也学不完。

因为我们每天每时每课都在不断更新里面内容。跟着我们走就是了,让你永远站在技术的最前沿。呃。

我们叫做一对一定制。这句话意思是什么啊?我稍微给你敲两句啊。我们其实现在定制已经特别特别细化了。😊,一对一的服务的定制,这句话是什么意思呢?我给你举个例子,就是我会根据每个人的背景。你是大大本啊,本科。

大专生工作几年。背景。每个人的背景,每个人的基础,你是会SSM还是会spring boot,还是会了解一些spring cloud?算法又怎么样等等。每个人的诉求。你是想短期内跳槽掌心。

你还是想要追求一下进大厂,冲一下大厂啊,你还是要怎么样。好,根据这个来进行定制学习。好,看这里我给你举几个例子,比如说你大二大三。镶近大厂的。7加1加1帮你搞定。这最普世的啊。

也可以对你个人慢慢的进行个人定制。你大四想进大厂呢,这个该怎么办?我告诉你,大四想进大厂要比大二大三要难很多。原因是你要走。校招或者社招了。那么这个的话呢有点。这个跟社招进大厂啊,社招三年以内进大厂。

社招。3年以内的啊,基本做这个好吧。呃,如果是说来给你举个简单例子,你你我我我就想跳跳槽涨个薪水啊,短期内的比如说一个月我就想涨个薪。跳个槽3加1把,你搞定。再给你举个例子,你说我说全面提升。

整个MCA的架构师,一个项目带着你就淘宝那个项目,直接带着你所有的这些知识点全部都给你带起来。我零基础怎么办?没关系,A课程一直到MCA课。ok。有同学说了,老师,我那个就想进特定的某些特别牛逼的大厂。

比如说字节字节特别看重算法,没关系,左老师算法可以帮你搞定。算了从0。一直到。google级别的算法,我们的课程呢。有一个谷歌的老师啊,还给咱们讲了谷google老师的这些个算法OK。就总而言之。

言而总之。我们的课叫做一对一可定制的大学选课制的独立升级的这种课。不知道大家能不能 get到这一点。好。这是所有的课程。这课程学完之后是一个什么效果?其实这课啊我们自己说牛逼也没啥意思。在这里啊。

就是每天你如果观察观测我们这个界面的话,你就会知道啊每天都会有新的。

我们的学员的一些好消息传过来啊,这是这是今天最新的。学完课大概就这么一种效果。这是到30万了吧,这是涨薪7K啊,干了。呃,一个多月学了6个课,掌握的不是很扎实,一个月看到了吗?涨了7K。

这课一个月就让你涨了7K,这还不是说是特殊现象啊,这是一个普遍现象。我们一般情况下会向你承诺3个月让你涨5K,每个月一年你就涨6万,入职一说涨了6K,课程很有帮助OK。女生入职京东涨了50%啊。

这个女生也是啊,你你们看我们我们在群里头啊是怎么对她进行服务的,看到了吗?这都是老师的一步一步的聊天。哼。很辛苦的。嗯,我们现在正在做自己的APP做自己的论坛。当我们这些工具齐全了之后。

我们打算撤掉这个一对一的这种这种这种服务,好吧,这个太累了。没这个老师,我我现在手里手机里有几千个群,快服务不过来了,希望大家赶上末班车。Yeah。晚上呢是我们的12点之前的一次秒杀,好吧,10点开始。

这课呢后面的我就不再提供这种服务了啊。这个服务比课还值钱,你就自己想吧,有20位你的师傅。从洪七公啊一直到聂小莹。带着你,你就笨如郭靖,也全部能给你带出来。啊,但是这个服务实在太累。

我们后面会考虑把它砍掉。抓紧。一年运维转账了,底薪干到30万看吧?这哥们儿是一年的运维。后来我建议今今天下午还过来了,今天下午还到了我们公司呢,跟我聊了几句天儿。我后来建议他呢,还是哪个工资高。

现进哪个,因为他薪水总体还是偏低。25岁英语专业5天突击就干进携程了。携程回复16乘15。5天5天。啊。就是老师的定制帮你专门的一个路线辅导,就牛就大概这么一个水平的。牛逼过程好吧。

不是不是说我们自己吹牛逼,好吧,就是你你们自己可以去随随便便的看这些信息啊,聊天记录。以及包括什么呢?

包括评价啊,这是学学生学完之后的差不多1000多条好评,1300条好评。咁嘛。自己看就行了。啊。名济实力啊就不说了嘛,追加评论买到就是赚到是吧?这是课程的广度和深度,这都是追评的啊。

267个小时学完一个追评。哦,总结一下我们自己的这个课程。很简单,这个课程叫做你只要肯来。带着人来就行了,剩下的一切全交给我们。只要你愿意听话。你告诉我你的诉求,老师告诉你一条路线,让你学啥你学啥。

让你什么时候学完,你尽量什么时候学完。你的诉求直接搞定最简单最简单的诉求,我相信大多数同学应该是要涨薪的这种诉求吧。3月涨薪5000。到不了的退款。前提就一个要求,听话。Yes。

教我们课只要你听话会达到什么程度?嗯。这种。就算你是比如说是。这样的吧,找找找几个例子。就烦这不听话的啊,自己也不知道你的经历啊同样是一个小时。我告诉你应该学这个,我我告诉你应该学这个为啥?

因为这个在今年最重要,你就学它就行。不要给我讨价还价。自己不乐意,非得学别的。有这种的学完之后达不到效果,回过头来还得找老师帮你重重重新规划。这个没招,你听话就行。

比方说我给你举个例子,你像这种的38岁的女成员。我也能帮你找出出路来,看到了吗?年薪四0的offerOK它很美的,原来找工作找不着的。特别想在公开课的时候能够多影响一些人。

让他们在职业生涯中规划中尽快走出迷茫。人家会是以为我是托,没托,咱们这没托。😊。

39岁大龄乘务员薪水翻了将近10倍,这就是我们课的威力。咱有同学说老师我赚的钱赚的比较少的,我能不能够得到收获?我告诉你啊,就找一个有一哥们儿是翻了5倍,他原来是在长沙拿5K直接。干到杭州去拿了25。

他拿的非常的少。

像这种半年涨9K的啊,这都很很很轻松的事情。干半年薪水翻了4倍。原来学5K现能干到20K,这个还不如你长沙那哥们儿。

当然还有一些特别快的啊,像这种高中学历,上海30K。

月薪呢。大专学历学了不到一个月,薪资翻了一倍的。直接是嗯。老师牛逼是吧?没没没办法,就就这么牛,我们想我们想低调都不行。学俩月涨3K的这算少的了,俩月涨3K一年有3万多。

好,这课今天晚上的秒杀已经10点了,秒杀已经开始了。今晚秒杀。掌新记的秒杀。Here。零点秒杀截止。这一课今天晚上腾讯的8000的优惠券,一对一的规划已经进入倒计时时间。今天晚上的规划啊。

后面再报可能就没有这个了,一对一了。呃,今天晚上报名送樱当红州键键盘一个,不要可以折现。9月9号开启的源码玩,15号开启的,我们要开启的多线程第二版做了什算码坡全都有。找丨小丨姐姐抓紧时间秒杀,千万别错过。

错过今晚你绝对会后悔。价格12000多块钱。这12000多包含着对你三个月每个月涨薪5000的承诺。放心。老师这的课没坑,你来就是了啊,只要你肯来,我一定会带你飞起来。Yeah。北方云天若今年32。

明年明天明天3月份明年3月份吧,50万年也有希望,你现在赚多少钱?北方云天因为你很多东西我需要查一下你的背景,你现在要每年就赚15万,我没法让你50万。但是你现在如果说今年你已经赚到30万了。

上到50万的可能性就特别高,好吧。就这一课你们觉得值多少钱,你们自己想去。帮你搭各种用环那样不你掏钱。当你落地整个的云的东西,如果在线下学这课没有10万,你真拿不下来。好,只有这个线上。1万多块钱。

没有比我们性价比更高的课。他有可能同样的,人家你注意问啊,注意多多去问问人家是啥一周就讲三次课,每次就讲2小时。大概讲个8个月,收你五六千块钱。平均每个课时200到300。我们是多少?

2000学时已经讲完的,接近已经接近2000学时,还还有好多没讲的。正在直播的。总共12000多块钱,平均每课时5块。为什么腾讯逼着我们拆分,你们知道了吗?没招啊,现在就是打擦边球。

深圳12K可以提多少换了吧?大哥,你这你怎么你你怎么。我我觉得你你你你你也你这个好熟悉啊。王老王,你好,天天在是的。12K你就踏实来吧。Yeah。哎,别的不说整个什么18K啊。

这一类的都很很轻松很轻松的啊。可以先报名这种空着再选,没时间。啥叫没时间啊?你天哪。来给你看看看看我们后台。你达到效果就行了。你看这后台这些都是原来叫耗长没时间的,到课率0。7%,10千节课就听七节课。

😊,整体完成度百分百啥意思?直播没跟上,跟了录播了,就这么简单。录播也可以,录播还可以两倍速呢。最后依然得到很好的效果,知道吧?我们学课程是为了啥?为了掌心,为了跳槽,为了得到更好的人生轨迹。

这个事情比别的都重要。什么叫更好的人生轨迹?如果你自己走,你很可能走这样一条路线。到达一定年龄之后,我开始走下坡路。就在今天这个点上。跟着这20位一线大厂的老师。你的人生轨迹很可能是这样子的。

你知道这个差距有多大吗?所千万千万不要在以后的某个事间段后悔说,2020年的9月12号,马老师带着20位一线团队的老师想带着我飞。但是。我犹豫没参加。你这辈子的亏损。大概就这么大。多了也不敢说。

每年10万肯定有。因为课程。课程最高可以给到你什么程度,你们想看看吗?给你看几个学生简历,这是课程一般可以给你给你到什么程度,大专生。这哥们儿是大专。就写了5条。五年一线开发管理经验,负责项目什么的。

这个稍稍有夸张。像这种东西,你教给老师,老师教你怎么做就行。构建高吞土低延池分布架构缝布经验。MCA可听完,这个没问题,放心吧。JDK各种集合队列所读现成高并法老师讲的东西。

面试常问的数据结构与算法设计模式。我跟左老师一块讲的。各种DC垃圾回收算法,JVM调的经验。我从最基本的理论开始给你讲,一直给你讲到各种各样的啊。咱们今天调的只是PSPO还算比较简单。

还有比较复杂的G one,还有比较复杂的CMS各种各样的日志该怎么读?只要你学完,你完全可以这么写,这么写的效果是什么?阿里给了他4次面试机会,当然没进去,这个没招。并不说大专进不了阿里。

阿里给大专好多机会的。但是最后进的也不错,60万到70万这样一个年薪。进的融360说为什么不固定?因为这里面有股票,它的股票是浮动的,好吧,很给力的啊。这是注意这是普通课,听懂了吗?

这个差不多就是学我前面所说那个高程课。还有同学说,老师,我要真把这加构课全学完,什么效果?好,看这里全学完就这个效果,你要真能全学完。看这个简历就知道了。差不多是这种水平。自己读一下吧。就是你简历。

你你的简历就可以这么写了。😊,好,这个简历120万年薪。最近刚跳槽到字节了。200万。刚刚跳完槽。我就跟跟你这么讲,就是你的人生轨迹发生改变之后,就越牛逼的人就会越牛逼。越差的人就会越差。

这东西就是骑自行车。这就是做汽车。我希望你今天坐上汽车,不要在原来的自行车轨迹上甚至步行的轨迹上跟那儿浪费时间,浪费生命了。这是他的项目经验。好了。当然还有更高的,你还想看吗?算了,别看了啊。对。

有有好多呢你没达到这水平。我给你看完呢,你自己。空于恨啊,觉得自己做不到。其实很多东西只要你拼。老师会告诉你哪条路线来跟着老师拼就行了。能拼到啊。好。课程别犹豫。找到小姐姐。参加今晚的秒杀。

一对一的这个学习规划是比什么都值钱的东西。ok。是不是加班贼多才要高薪?我就想问你这么一句啊,如果说你不加班,年薪给你10万,让你加个班996,年薪给你100万行不行啊,可以吗?加就加嘛,实在受不了了。

我就找一别的。今天有学生还还还挺逗呢。我看我这微信里这个电脑的微信是不是同步过来了?嗯呵。Yeah。今天有学生啊,找找。嗯。就是你你你记住啊,就是你的你的技术水平越牛叉的时候。嗯嗯。呃。

你的技术水平越牛叉的时候那个。你你的选择面就越宽啊,这非常重要。你看啊你看这小伙。这小伙呢是在外地,在外地之后呢,他想到一县城市发展。然后呢,他就拿那个滴滴呃,跟那个用友呃,两个offer。

当时呢滴滴那边面试的时候,他还在外地,所以他没他就他他就没没面成。后来就入职用友了,四点半就下班,看到了吗?四点半就下班。😊,所以小伙伴们,你们的技术越牛叉的时候,你就会选择面就越宽。

你可以选择加班加班的公司。也可以选择像外企啊,或者像传统企业呀这种不加班的公司。这是你有选择了。你如果不学习不进步,你连这个选择都没有。没有关系,好吧。用油可不是4点半下班,我在用油。哎。

没没没没没没办法,人家现在HR告诉他的14点半下班。啊,也许拥有的某个部门吧。嗯。有年龄限制吗?几岁不建议报名了,目前还没有什么年龄限制。我们年龄最高的是49岁报的名。他的诉求就是我想了解技术。

他在公司很稳定的地位。管管理,但是我想了解技术,想管理的更好,这是这是他的诉求。现在你想涨薪的呃年龄比较大,就刚才我给你看的那个39岁的,39岁,他依然可以涨薪翻一倍啊。

还不是说还不是说涨的那个特别咋说呢?就是特特别少的那种,还真不是啊,那哥们是翻了一倍啊,39岁。就说看你看中什么。你你觉得你年龄大了就不不不要进步了是吗?那我就没招啊。

但是咱们这个行业你不进步就会被淘汰,非常简单。这行业就这样。这不是吗39岁大龄成员,薪水翻了将近100K。嗯。就在天津。杂七杂八的补助。6乘13虽然全北京杂七杂八补助加起来可能又流失。我记得是啊。嗯。

人家38岁的都在努力,你多大了,不努力了,打算。嗯。Okay。1辈分都走30万到60万吧,应该是啊他一年就干的多多了2二三十万。你说我们这课才1万多块钱,他不值吗?而且这1万多块钱的课呢。

你以后遇到过什么什么难题嗯,你们公司技术选型了,你不给你不知道跟怎么跟领导提提建议。这么多老师做你的后盾。你就算请20个顾问多少钱,你自己好好想想过吗?就这颗。全中国最值的性价比最高的。我们要说,第二。

没有人敢说第一。想学习的来这儿肯定没错。不想学习的,我就没招了。当时boss之孙写的4人加班去了9得73个月。那就离开,拜拜。这有好转岗吗?搞管理岗可爱美丽些。每次我听到这个转岗转管理岗的时候。

我就特别烦。你知道这句话害了多少人吗?嗯。不干不给你看今天聊天记录了。今天有个小伙三十二三岁了,说老师,我转了管理岗转了好几年了,我现在想转回技术,为什么?因为我发现我招的人赚的比我都多。

而且人家聊的技术我都听不懂。大哥各位大哥。您老人家做一个技术的人。技术不行了,转管理,你扯淡呢。你给我记住我现在要说的话。叫做技术管理两条腿,必须都得给我走硬了,你才能在管理技术这条路上走的越来越远。

叫技术加管理。给我记述这句话叫加管理。就这个转字不知道害了多少人。我不知道今天在座的有没有很早很早就转了项目经理,离开技术一线。过了几年之后,你突然间发现你踩的全是沙地。有没有?有的话给老师扣个一行吧?

有羊仔。千万别这样,小伙伴们,你知道这个真是害害死人啊。如果你想走你想走什么样的路,看这看这个简历吧。看这个简龄。这小伙的学历也不高。学历也不高。然后呢,技术呢人家没放弃啊,我同学说学历不高是硕士。

怎么学历不高?仔细看就是了,这哥们是大专生,而且还是非计算机大专。当然。哥们现在已经是40多岁了。他写这简历的时候已经40多了啊,跟我年龄差不多。他呢这种40多的简历啊。

跟这种这是这是黄老师20多岁的时候写的简历。你你大概是五六十万的年薪这样一个简历。嗯啊40多的简历跟30多的简历,30多岁大专生简历跟这个。40多岁的这种比较牛叉的人的简历,他就完全不一样。

我我重点看的不是想让大家看这个,你主要看它的发展历程。你看看。扬州大学热加工工艺设备大专。第二专业才是计算机应用。好,下面这个什么高等数学排名成绩,什么第一等奖、二等奖。

这些全都不要管这个东西叫做简历技巧。简历技巧这件事交给我们的老师。交给我们就行了,你不用管这东西也很重要。非常重要。以前有同学写就我们帮他改了改简历,就涨了2000块钱,每个月。一点不有。很重要。

但是你不用管交给我们就行。你看他的发展历程。南京大学自考的本科,人家在补了学历了,看到了吗?不断学技术,不断补学历。最后,工商管理的硕士MBA合肥工大的MBA。他的人生发展路线是值得借鉴的小伙伴们。

技术学历管理,当然还有什么沟通、情商、人际关系。这个构成你综合的素质,才能让你安稳的度过中年危机。只有这样。您您千万不要再说技术转管理了,你转个屁,技术不行,你怎么你怎么管搞技术的人啊,别扯。

哥们儿要的年薪。88万到13万的月薪。一年100万到160万。有同学说老师会给吗?会有人给吗?去年我们的内推。那推于岗位里头有一个是龙湖地产。人家就要求150万以上年薪的啊。

8年以上研发经验带领研发销费,这是必须得有技术,必须得有管理。就是给这类人准备的第二个岗位稍微稍微少一些的,也有120万。房地产公司。非IT的一样也会给那些个在大厂待过有管理经验的人以很高的薪水。

所以这个大厂和小厂的区别就在于这儿。同样35岁,你从大厂出来,从阿里出来,有一堆的这样的公司以百万年薪去请你。你要是中小公司出来,你就是走的这条路,知道吗?自行车失业了。这是在大厂的。

还是的话越牛逼的就越牛逼嗯。我们可牛逼牛逼了。这个都是主动找到我们要求内推的。字节跳动的直播研发负责人看到我们课程就觉得有不错学员,为啥?课程牛意啊,这个没招是吧嗯。这是4月份,今年4月份找到了。

建立下来联系。我最近推,你想有好几个学生就直接就直接就干进大厂去推进去再说。当然你也不要有误解,是不是推进去就一定进。哎,关于内推这件事儿,有有多少同学有误解,就觉得哇内推是一条捷径。

别人推进去我就能进去了。来,有没有谁这样觉着的,有的话给老师扣个一,我认识一下。内推这件事有需要我解释一下的吗?什么叫内推?不是我要真能说内推进去,你一定进,那我干脆不要讲课了,我直接卖人头就行了。

来吧。能进一线大厂10万0个,有没有人想进的?有的是。但是内推是这样吗?谁要是这么跟你说话,直接拿大嘴巴子抽他。内推什么样的?内推叫做。人家正常的HR前面有一堆人排着在面试。内推插个队,优先面试。

听懂了吗?实力才是根本。内推就是帮地简历加一个人情,说的很对。所以大家也不用对内推这件事儿看的特别重要。你只要简历水平够了,我给你推进去,企业还欠我个人情呢,你是人才。企业很需要人才的。嗯。

内推成功率高一些,也高不了太多。现在企业都学精了,人家招聘人一定是要独当一面的,你只有达到这个实力才可以。你就是插了个队,也许你不插这个队,人家后面一个人就站在这坑了。

所以趁着我们现在非常熟悉大厂的这些坑,趁着我们现在。非常熟悉人家现在看中的技术是什么,然后都我们都进行了讲解。等这些坑占满,你就后悔死。啊,你来我带你飞。带你长个跳个槽,长个心呢,真的跟玩似的。运气好。

带你进大厂了,你开展更以后更美好的人生。你不来。这些坑你将面临的就是我们学员的竞争。你可以试试看啊,学完我们这些课的这些学员。来跟你竞争。你自己好好想想,你能不能竞争得过。其实毫不客气的讲。

现在为什么面试越来越难。培训公司在里面推波助澜。我们呢基本把我们的学员定位在全国的前10%这种水平。引流好吧。面对的就是一线达成。一流企业。有同学说老师我想我想我就在二线怎么办?没关系,降维打击啊。

学个百分之五六十,最简单的像那种二三线的厂的,二三线的。这种城市前5%岗位你就可以平摊了。这不是我说的学员说的啊。嗯。记得有学员啊,找找哇太,因为就业信息太多了。你挑的挑了一些给它列出来。搜一下。

咱们学员说了吗?二线城市技术平刚啊。之前拿多少14。5啊,现在还没学好,找点好好学习,有再兼职学习,先干一年半载的啊,我觉得把我们的课程学完真的可以二线城市躺着走。就这样啊。

所以你不要问我说我我在厦门啊,我在苏州,我能拿多少钱,别问这事儿,不用问。😊,你们城市前5%的岗位,把我们课大体学完半年左右。你们城市前5%的岗位所要求的技术,你就到了。嗯。好了。😔,需要课的别犹豫。

你不要犹豫,今天晚上就是改变你人生的机会。干就是了,有很多人就特别犹豫,犹豫来犹豫去,很多机会就在这种犹犹豫豫的过程之中全部浪费掉啊,人生就这么废掉的。ok。呃,有需要了解的小姐姐的找丨小丨姐姐聊啊。呃。

有对咱们课程有兴趣的,有需要问老师一些什么的什么问题的,在这问,抓紧时间。还有一个呢,晚上的你技术,你说我搞不懂,需要问老师的问。哪个更适合初学者,这都是进阶课。

初学者的建议从我们的A课程零基础的开始学,好不好?什么场景用多线程?多线程场景非常多,你写中间件用的是最多的。写业务上的话呢,比方说刚才我讲的这个小程序线程池。ok。32岁女生转账不靠谱吗?

这东西我需要了解你原来的背景。一般来讲,32岁是转成员的最后的时间啊,当然这东西呢也分人啊,有好多人呢他比较牛叉,38岁转那我还真遇到过啊。呃,今天1。2万报名是零基础吗?对,零基础包括包括零基础。

我是小白,能不能白嫖一些基础的,完全可以。我们现在进节课是包括送给你一个基础课。键盘只送钱十。对,没错,送键盘只有10个,10个折,10个键盘送完就没有了啊。所以大家抓紧时间。多县成多县成嗯。

都是马老师写的书,不是不是有两本呢是我我我在讲课,然后给总结出来的,有一本是周老师讲课总结出来的。后面还会有一本啊,我们第四本书很快要出了。myciical调优是梁老师讲课总结出来的。

如果一开始问老师很基础的问题,老师会很不耐烦的啊。我们有专门的基础课老师,此人姓赵名赵珊珊,我们有自己的专门的基础课的助教。所以不会很烦,你放心,基础课才是真正的保姆式的服务。就是他们在群里。

你随时都可以问他问题,他基本上看到就秒回的这种啊。呃,但是我们进节课并不提供保姆式服务,你记住这一点啊。不需要运费。对运费我们替你出了,就是这么体贴。怎么领书?莫及,我们是。课程结束的时候才送书。

课程结束还在我们直播间呢,送你一本书。32岁女生,本科是文科之兼会计,零基础,现在能学逻辑所学能力还行。我觉得这件事儿是这样的啊,叫做有风险,有收益。如果你没有别的更好的选择,你可以朝这方向拼一拼。

我很难保障你说你现在能达到一个特别好的效果。学这东西包括学任何东西都是肯定是越早越好。像你32岁,你得拼。我给你讲几个故事,这叫蝼蚁。诶。我们我遇到的就是转行零基础转行的年龄最大的是1个38岁的。

年龄第二大就是32岁,听听懂了吗?我再说一遍。年龄最大的是38岁的,年龄第二大就是32岁。他们是怎么做的?为什么他们在这种时候去转行?因为这哥们儿叫投资失败,欠了一屁股债。这哥们儿叫家庭破产。

他们家里原来是县里头特别好的一个企业,县县里的企业挖沙子的。他是沙场老板的公子,家里。破产。然后欠了一批股债200万。去年的时候,这个哥们儿在我们直播间做过节目啊,我们当时几个人跟他一块聊天儿。

他当时聊起那会儿的事儿来,眼眼眶都红了。当时他学完之后的面试过程,大概前八家,面了8家,没有一家成的。他站在那个过街天桥上看着北京三环的滚滚车流,当时就是真的想跳下去。但那时候呢,他小孩还小。

父母破产欠了一屁股债,他只有撑下来。32岁到35岁的时候,他大概拿了40多万不到50万年息。然后呢,债还的差不多了。牛逼吧。但我告诉你啊,人家是什么样的都这种压力,欠了债的。

所以你要是在这个年龄想转这一行。做好吃苦的准备。不然你真不成。Yeah。嗯。没得选这行还是不错的。因为这行呢,你只要拼还是至少有就业机会,能够找出来你你你能够有安身立命的地方,没得选的时候。

有的选要比较。32岁的妹纸。这能吃啥口不就敲吗?嗯,晨晨嗯。一看就是年轻人的话,32岁的妹子找个好老公。😊,嗯,我从来不建议女生放弃自己。然后去依附别人。你的人生没劲,别聊。

什么宅什么什么什么宅输的码怎么扫?课程结束才给扫。38岁入职互联网企业面试机会都很难得到,简历包装很多,简历必须得包装。你32岁也得包装。28岁也得包装,不包装是不可能的。入职互联网企业面试机会都很难。

他至少有一些人脉,38岁做投资的能一点人脉都没有吗?最后就做唯唯唯唯品会嗯。越学越回不了老家了。呃,你在。大城市呆惯了,你肯定回不去。小城市的那种。工作氛围,那种人情世故,大城市全没有。

尤其是那个特别不喜欢去搞人际关系的这些,其实你在小城市呆不住。别说小城市有很有一些像我原来认识的同学,西安的。他在北京呆惯了之后,西安都回不去。中国城市一定会越聚人越多。所以一线城市它的发展,它的。

各种的资源的聚集一定是最多的,机会也在这儿啊。是为我就是唯品会的。好吧。这么说,快把人家的我隐私给暴露了。错过了什么错过了什么算什么。什么是持股的具体表现?持货有什么代价?什么是持股的具体表现?

我们有一个女生在这学习的。他有两个小孩,白天伺候着两个小孩,晚上半夜学。大概就睡几个小时。Peno,我是老VIP这衣服还没有就没了,找啊,抓紧时间找咱们小姐姐嘛。只要你找总是有的啊。

投资中国银行原油了吧,嗯不知道你是怎么知道的?😊,年薪770个,那得多牛叉才行,感觉智商达不到。那那就不用学了。您现在多少钱就踏实待着多少钱吧,什么时候淘汰,什么时候为止。😡,我是连老师的服务对象。嗯。

两个人服务很给力的。请问您这个具体教什么?我想摘了教。课程比较多,从高层到项目,一直到架构师整体的这个课。呃,课程内容如果不了解的话呢,随便扫咱们一个小姐姐。

找他去要就可以了啊,找找他去要我们的大纲,你就了解了,好不好?讲高等数学嘛?成语员的数学里头会讲一部分高等数学,但是呢并不是专门讲高等数学。老师,我想做字节跳动的首席架构师。呃。了解你背景。

你先你先别做梦。这东西不是拍胸脯就能实现的。您老人家知道字节跳动。字节跳动的首别说首席架构是。普通普普通的。程序员或者说高端一点程序员拿多少钱吗?你们想知道吗?有没有想知道的?正知道就说一下。

会飞的瓜牛1000万。有可能啊有可能。无图无真相给你调图出来。老嘴说没劲。来看这图。字接跳动北美。当时没有没有被美国干的时候给的薪水,自己瞅一烟。所以你想成为字节跳动的首席架构师来奔着这方向学。

能看懂吗?84万美元的年薪。50万股票。呃,应该是10万的什么签字费吧,24万的补贴。来吧,干吧。美刀对美刀。

。え。shit哪去了?我还在吗?

我还在吗?我还活着吧。哦,还活着。突然之间我能感觉。画面一下全清了啊,嗯哼。年薪580万。yes。呃,梦想无极限,你得动手做580万。估计在座诸位啊,包括我们自己都有可能很难达到。但是啊。

我觉得学东西也好,教东西也好。我们为什么怼一线大厂一流城市?啊,不是那种像什么呃长沙呀、武汉呀这些二流城市的培训培训者。他们面向的也就是个30万50万年薪到头了。

我们直接给你怼到100万年薪以上到200万年薪。因为你学东西就算学一半儿。就算学4分之1,你发现没有?你达到的技术水平。都和人家的那个二三线的那那那种课程差不多。学东西呢要让自己学狠一点,叫做这个取法。

古代有句话嘛,叫取法护上。得乎中取法乎中得乎下。就很多时候你要给自己留余量。好嘛。580万比蔡崇信还要牛,怎么了?现在中国互联网界有三大薪水最高的公司,你们知道是谁吗?第一个叫拼多多。第二个叫自节。

136华为。所以各位小伙伴们不要认为阿磊的薪水给的就是最高的。呢不是这么回事儿啊。自己拼多多、华为。有同学说还包括华为呢,对华为的很多呃有一定工作年限的员工,他的所谓的工资只占他总体收入的3分之1。

所以一般来说,华为工资是多少,乘以3是他的总体收入。拼多多是真高,华为最难进吧,倒也不是啊,华为现在老搞些OD之类的,所以你要曲,有的时候是曲线。呃,要想直接进的话,要求水平确实比较高。小二瑞是29岁。

三本未婚,目前做电话客服一个月3000多来这种29岁没有问题。Java web前端软件测试排除哪个最容易上手,软件测试最容易上手。但是他的薪资呢也是偏低的,最难上手的是java。

但是它的天花板也是特别高的,所以有有利有弊。爬虫不建议去玩,因为这东西面儿特别窄,还容易出问题,不要不要不要不要学这个啊,前端后端测试都可以。我们也有自己的测试课,今天没有重点给大家介绍。

如果你想了解的找丨小丨姐姐聊。我们测试课有自己的特点,叫做不就业,不用你花一分钱。你不是现在做电话客服吗?我们现在的测试课是这样子的啊,叫做你先来学。基本上两个月带你进初级测试岗位。就不了业,不收你一分钱。

你一点风险都没有。说到这儿呢,我想给大家讲个故事啊,就这个这个扯的有点远了。我们为什么要做这个时个,很多人可能想不到。😊,这测试课面向的是谁的?面向更低端的。比如说你初中毕业的。职高毕业的学文科的。

Okay。做送快递的啊,做客服的这些。为什么我们想做这样一门课?就是当时啊我们几个老师一块儿去坐地铁。大家知道北京地铁呢安检比较严,北京地铁安检的时候是有那些小哥哥小姐姐,大概十七八岁。

2是郎don sir。他呢就在那儿拿一个仪器上下扫你。我那当时就是说这么年轻,20岁啊,黄金年龄啊。做啥工作,哪怕你做个销售都比这强好多。拿一仪器每天就在那扫,然后没事了呢,拿一手机就搁那玩。我的妈呀。

这真的是太浪费了啊。😔,那是外包啊,没有编制的。就这些这些安检的全是外包,没有编制。后来我们说要不然。我们做一个课适合他们学的。好,我们做了一个测试课,适合他们学。但是就算是解释给他们听。

他们也没人愿意来学。那就是就一个算一个吧,我们也不收你钱,你只要来学俩月行吗?觉着测试适合你来学继续学。然后就了业还我们钱,还一个月工资就行。我让你4000块钱就业,你就给我们4000。

让你八000就业就给我们8000。救一个算一个说我没让你救得了也,没关系。一分钱不收。就当做公益了。主要真的这批人看上去太心疼了。好吧。这样的工作。老头老太太退了休的去干。啊,你让年轻人干这种工作。

太浪费了。就是我们做培训呢,还是有自己的一些情怀在里面啊。当然我说想让他学渣文,那他也学不会啊,也没有必要嗯。是。所以你真的你你你同学啊,老婆呀、女朋友啊,如果真的是说我想进到IT行业。

我也不想担任何风险来就是了。好吧,真的没有没没有一1一点坑都没有,你就了业给我们钱,不就业,一分钱不要啊。老头老太太工资比年轻生高太多了。对呀。😊,哎,一招。😔,普本毕业软工入职银行项目运维课程怎么学?

从零开始。一一年运维,几年运维转的好几个,不给你看了,从零开始,一定要从零开始,它是扎实了,把基础给我打好了。OD就是最好的外包算是一VE了。没错,OD大概有20%到30%的会转账,所以你拼就是了。

这就是变相的剥削,等着你拼。P pin pin。我们11点送书吧,好不好?现在是10点50了。嗯。啊。只有架构方向,还有ID其他方向的课程吗?呃,那个有。课程比较全,现在运维方向有安全安全的课。

测试方向。测试呢。有我们的前端课前端课。Python。他种。数据分析。大数据开发。python全战。java小白到就业。java的进阶课。今天只摘个小白就业加进节课。就12000多贵吗?谁要说这颗贵。

谁就真的没了良心了。到入养学后3年内拿到年薪100万。看你的技术跟你的冲劲了。三年百万我遇到的啊,年轻的,我不知道你多少岁。30百万到现在为止,年轻的我仅遇到一亿人。此人姓黄。

是我们自己公司的CTO他在美团离开的时候是85万年薪加股票。我把他从美团挖过来,美团当时都快跟我急了。听我说。有很多那个企业做培训的呀,找找找老师都是差不多二三十万三四十万。在那个线下讲了很多年的。

就讲一个固定的某个课的。我们的理念不一样,我们想请到的是整个一线大厂里头在待过的有实际项目经验的,能把实际当中的经验讲给大家听的这样的老师。不管他多贵。只要我们有正向收入,我们就愿意在老师身上投钱。

这帮人值钱知道吗?有一个牛逼的老师带你两句。比那个。普通的资质平庸的老师教你半年都要强的多。想看看他简历吗?他大概在一年多的时候入职阿里。就这份简历。这份简历是在一年多的时候入职阿里的简历。

大概那时候是拿55万不到60万。入职美团的时候是85。今年2020年。24岁。Yeah。不到25岁。所以你想三年百万来干就是了。水平到达这个程度的时候,会有百万零星的岗位等着你。What。

what what?What, what, what。那时我刚学完多燕城下面该学什么?欢迎。呃。下面不知道该学什么的时候,找到咱们的班主任老师,然后。班主老师会拉一个小群,老师会专门告诉你。

你下一步该学什么?周耳讲可以带进。yes。周老师讲课叫做我我我们讲课大家伙啊吹牛逼点叫,大家伙得跪着听。周老师讲课呢你得趴着听。屁股朝上不敢起来嗯。简历还是很朴素的,关键得货真价实。没错,原因就在这儿。

当时阿里的人找他去面试的时候,说你才23岁多啊,那会儿才23岁多。你写这么多的简历,说你是在哪个培训班培训呢?给他拎过去,从头问。阿里面是有一个特别好玩的地方,从屁股开始问。P5问一堆,哎。

没难住来P6又没难住。P7还是没难住P8。黄老师当年讲过P8问呢,他什么问题?AQS原码。还没难住。啤酒。P9问什么问题?0X80调用过程。80终端的调用过程,lininux内核的东西。依然没难住哎。

后来说好吧好吧,确实水平比较高。给定P7的薪水,但是职级只给定了P6,因为太年轻。阿里太年轻的,不给P6,不给P7。老师刚刚有个逗逼趁我不注意,发些莫名其妙的信息,现在感到好丢人。这个逗逼是谁嘞?😊。

是你的男朋友吗?0X80不是0X86吗。0X80呢叫做80中段,叫做软中段。86呢叫做。计算机的体系架构两回事儿啊,别扯一块儿。是我的同事。肯定关系不错了,共用同1个QQ号很暧昧了。0X86就可以这样。

对呀。0X80讲啊。😊,只要他要面面试的东西,我们就讲就是我我我我觉实刚才没有跟大家说,我们会深入到什么程度啊。其实主要怕吓到大家,就觉着啊我是不是学不会啊,你不用担心啊。

就是我们老师们讲东西都是讲的很很很通俗易懂的。😊,我们讲那个啥,ho sport源码知道吗?😊,这里面公作公认比较难的课呢,实际上是周老师讲的。这男的课呢叫做IO的知识。你只要愿意来听听看就知道了。

这里面呢公认比较难的课呢是。是。这是我这VM的课,制周了reis课SU调U。那我找一下啊,去哪儿了。Oh。哎,这块儿。我告诉你啊,公认比较难的课是这块这块的课叫做内存与IO这课是超级难的。

从那个C1K啊的scket的BIOTTP参数怎么玩,网络编程服容器一po到那个手写net的RPC到网络IIO到底怎么玩的,这块是比较难,而且推是帮着你实现推导。推导过程。哎,这块稍微难一些。

你可以往后放,不着急啊,然后这个呢课难完之外呢,就这个课最难了,这课叫算法与数据结构。从那个复杂度对数器二分法到链表规并啊,比较器啊等等。统统链表、二叉数、贪心暴力递归动态规划。

动态规划呢讲了大概10个小时。进阶版呢就是单调战非布弹切数力啊,各种算法,KMPmanature莫里斯变历啊切座术。到打表技巧到速度啊、还哈奇函数啊、有序表啊等等经典的各种各样经典的面试题。

这块是比较难的,但是这种东西呢需要你慢慢的修炼,知道吗?制作神yes。传说中的左成。对,没错。就是这种东西呢是需要你真的需要你慢慢的修炼。这些算法一般工作中用不到呀,恭喜你啊。

你可以作为一个螺丝钉钉在那个。钉在这种工厂的生产的这种生产生产呃生生产线上,你就钉在这儿啊,只只是把自己当螺自营来用就行了。就我说用用是用不到,但是面试。如果问到答出来,您老人家的年薪叫做50万。

便是答不出来,您老人家的年薪叫做20万。哎,这就是区别。工作中是用不着,但是他是开拓思路,是内功,是易筋经。你打那黑虎掏心,你天天打黑虎掏心,没错,是用不着。可如果你内力变强,易筋经变强了。

你一招黑虎掏心打出去,前面会倒一片。杨仔杨仔,你面的肯定是小公司了。二。0是算法岗二本二本非科班年时,我就不要学这个想涨心吗?想涨心来学。这还用说你才15K。小case了啊。等再看看24牛人的简历。

你有啥可看的,你想copy下来是吗?不给你看了。看两眼吧。放心啊,就是咱们课。即知识那那段东西学完,你就可以写了。就不需要那个还不还不说项目和架构的东西,好吧。你像这种的都我跟你讲的。😡。

我给你讲通俗易懂的,昨天听过课吧,通俗易懂,给你讲完之后,你还不敢写这精通,放心放心写啊。老师,我和我的同意都想去自己做手席架构师啊,加油加油啊,欢迎你们字杰,欢迎你们啊,找我内推,我新推进去。😊。

自己手艺教育师啊,年薪千万肯定是没问题了。算法不会写,只会看,也算是一种写和看是一个巨大的差距,但是也也可以。有的时候他面试的时候呢,就面试你思路,思路写出来就可以了啊。哇,11点了,我送书吧,好不好?

目前直播间有420人送你送你们420本书。老师都别说手机只能有一个,没关系啊,今天你来,明天他来嘛?轮着来轮值轮值首席。是。嗯。扫这码。扫码之后选一本书三选一。好。自己选好了,填好地址。

不如你掏一分钱给你邮过去。夏威夷想要马老师的亲笔签名来签给你。马上给你签。等着我打开我我的画图板。找到我的签字笔。开始给你签好不好?你大名叫啥呀?送给你。Yes。确。Okay。是的。Yeah。确实。好。

拷贝一下吧,拷贝一下。Yeah。只有奋斗,才能成就更好的自己。希望大家伙埋头苦干。响应我们***的号召。让自己在这个行业里变得越来越有竞争力。好了吧,签完名了吧嗯。老师逗逼说太浓的手掉过湿。

因为他的头发没我多,没关系,你自己拔掉好。你自己拔掉他就做不了了,就开始拧了。

你说小白兔小白兔,你掉毛吗?你说逗比逗比,你掉不掉毛,不掉毛的话,拿把你拿来用一下好吗?手机看的扫不上,先截图,然后在截图里扫。小白兔小白兔,你掉不掉毛?嗯,这个梗小白兔哪个梗啊?😊。

老师骚话怎么这么撩?什么叫骚话?老师从来都说正经话,从来不说骚话。啊,领完书了吗?这个码我可以撤了吗?听过挺恶心的。哎,嗯子呀。😔,注明你心理素质不够啊。单号会给吗?单号会给啊,没问题。

那个找丨小丨姐问单号,我们是京东的快递,京东的快递啊。VM多线程哪个偏实战一些?呃,多线程其实主要是为了面试用的VM会更偏实战一些。老师,我们要山库跑路了,加油加油加油啊。这一定要隐姓埋名。呃。

最好呢跟我们的另外一门课,我们另外一门课叫易榕树,你也可以跟我们学习一下。现在能有海外吗?sorry邮不了。有不了海外有。是。嗯,还的话。😔,课程呢一对一这块是非常值钱的。但是呢学着学员越来越多的时候。

扶不过来,这就没了。抓紧时间,这种福利并不是所有人都有。Yeah。都说别的也没有用,我觉着最合适了。哇,怎么又更新了一个。刚开始看到的还是这个呢啊,现在又又有又有两个又有两个,这应该是最新鲜热辣的。

我们来看一眼什么情况。收到4个offer入职美团。美团啊后来才知道面试官是VP美团让我写希望薪作填了45万1年。拉钩是这么多,一年可以拿1次数16限,试用期6个月。首期约车是这样的。

一点资讯是这个就差美团了。美团这边确定了。要你了。眼前这个几万块无所谓,对,少点就少点儿。美团毕竟是一流大厂。不错不错啊。太好了。一是课程班里面shaingBC的小课。

还有架构4期黄老师讲的分布式ID用就是美团的。先看这两个对比着集团的技术文档,就是美团进去之后该怎么怎么怎么怎么怎么学,都会告诉你。只觉得sprint克进了用友涨了涨了50%啊。

只有刚才那个我给大家看到过了,他用友用友这边呢嗯4点半就下班了,他主要看中这个,后面继续学习进达场嗯。

不错。😔,眼瞅着。眼瞅着人家就已经打开新的。职业空间了,你还等啥呢?搁那儿。逗比我搞的是吧?嗯,你俩这个。俩逗逼嗯。jakins彻里起不了了,重装重启。呃,有什么长沙好点的厂,长沙好好歹厂不多吧。

430不可能的,我觉得有点是,但是人家给的HR说的就是430。我不知道你们HR是不是在忽悠。😊,I。嗯哼。都科班,哪里能领书,已经领完了,讨厌,刚才让你领你不领。现在在想量没有了。嗯。

已经是11点10分了啊,小伙伴们领完书应该已经领完了,我把码撤掉了。就是我强调一下。一对一目前还有。抓紧时间秒杀没了,千万别没了,再后悔。成都先。周树人,什么叫?什么叫成都西安呢?

成都的薪水应该比西安稍微高一些吧,现在是四发告要转开发嘛,对薪资感觉还行。呃,我我希望你能慢慢建立一种。什么东西呢?就是你可以不用转,但是你一定要眼界要开阔,你懂吗?我给你讲故事吧。

就是我不知道在座有多少人啊,呃是这样的啊。反正那个。聊聊聊聊点小甜天啊,慢慢聊着玩儿。我你讲个故事啊。好,我不知道在座有多少人是这样的,是玩呃开发开发各种语言的啊,给我们玩玩玩玩玩玩算法的。呃。

需呃做点net的。呃,做C的,做回编的。做C加加的做swift的。而购的。开发java的。开发C的啊,开发C加加的开发说过了啊,开发什么colin的。开发前赚了。玩PHP的。甚至玩Rst的啊等等等等。

呃,玩什么archs啊啊。面特别窄的这些。呃,小伙伴们听我说啊,就说人路要想越走越宽,一定掌握东西必须得越来越多。我不知道在座的诸位,尤其是玩什么PHP的,尤是玩玩前端的,玩够的。

我不知道你们有没有问过你们的前辈最高能拿到多少钱。一般来说,只玩语言,最高拿到多少钱。这个我们称之为叫做语言的天花板。这语言天花板到底有到底是多高呢?我理解的我们了解到的不是理解的。

我了解到的做点net北京35K左右到头了,想找再高,您老人家找不着,知道吗?整个行业最高就给你这么多,玩C的也差不多,玩C加加的比这高一些,但也高不了多少。你要只玩知道吗?不了解架构。

这些比这个甚至还要低差不多22225到30。知道吧。你要玩够,可能稍微比这va稍微高一点点啊,也35左右,40差不多了。这哥们儿现在最惨。差不多20就算是不低了,而且往上涨还真涨不了。好,听我说一句。

这种东西叫做眼界太局限了。给自己设限了,说我这辈子他想找找那个轻松的活,你懂吗?找那个好走的路。我这辈子就懂这么一个,我就想活一辈子,完蛋。😡,我希望大家至少建立起来叫。架构思维。好,什么叫叫构思维啊?

绝最简单利润。你要盖一座大楼。这地儿啊适合用水水泥混凝土,你就用它适合用塑料,就用塑料,适合用木头用木头。作为一个软件的比较牛叉的架构思维,叫做这个地儿适合用牌粉,用牌粉,适合用java。

用java适合用go用go适合用C就用C。这叫你牛逼架构师。他并不会让语言局限自己的眼界和发展。好,这叫就比较合适,这叫做leaderlea级的。引领技术做出决策。好,这叫有钥匙。

即便你们现在没达到这种程度,这种层次,它的天花板200万没问题,知道吗?就是最最高的这种天花板。即便你们没达到,但我希望你们在脑子里存着这个嘛,我们见贤思齐,好不好?你不要躲,记住这一点。

这个时代最怕你躲要迎难而上。我们讲架构师课总是要拿一一门语言来落地。我们为什么要采用java呢?我给你举个最简单例子,拿那个现在最流行的java的后端的这种架构来说,后端架构来说不是java后端。

而是后端架构。最流行的架构是这样的,这层呢叫网络的接入层,我们简直称为网络层DNSCDN资源的静态化LVS index基本上都位于这一层。在列层把。所有的这些链接打过来之后。

进入到我们后端的叫API网关层路由熔断限流。OK经过它才会访问到我们的数据的微服务层。微服务现在已经落伍了。下一步要发展的就是我们的service mass叫服务网格层。别人讲吗?没有。

我们都已经要落地了,知道吗?servicem下一版的网约车,就是service matchsh的落地。就是你跟着老师这就永远让你站在最前沿,你落不了伍。好。数据的。服务层或者叫数据访问层缓存层。

数据持久化。链路追踪全链路压测安全在旁边等着监控。熔断限流降级okK好,这就是典型的一个互联网的架构。像这种架构。我要讲给C的人,他听不懂我要讲给ASM他听不懂,我讲给安卓的人,他听不懂。

但是我讲给java的人。他大致就能听懂,这是为什么做java人更容易成为架构师的原因。好有这块不知道我说清楚没有。所以各位小伙。不要让语言局限自己,好不好嗯。

是。澳们11点半吧,你们去骚扰小姐姐吧。🤧没有什么需要跟老师聊的,我就撤了,年龄很大,嗓子都疼了。嗯。思维和语言没啥关系。对啊。嗯,你们知道为什么我们要讲算法了吗?

我们为什么要请很牛逼的老师来给大家讲算法?左老师是国内讲算法第一人,好吧。我们为什么要请到这个?算法,你说跟语言有有多大关系吗?真没有,它就是一种思路,一种内功。你说IO的知识跟语言有关系吗?

没有我们为什么要花大精力花在这个上面?能能能体会到吧?这东西叫一通百通。我昨天给大家讲GC的时候,我是不是横向比较啊?我不单跟你讲那个java语言的GC,我给你讲C语言的,给你讲C加加的。

给你讲rat的。好,这个叫一通百通。当你到这种层次站在一个更高角度的时候,你会发现你的路不仅变宽,你的眼睛也会变宽。嗯。0点秒杀截止,不要犹豫,这就是全互联网最牛逼的架构课。老师,你要戒烟呀。

为什么要戒?我就不借,因为我从来不抽,所以借无可见。25倍的深圳音乐段能涨到多少?我要看你背景,我要看你的背景爱 stand。像你这种就突兀出来一句话的,我就很难给你做界定了。但是涨是肯定会涨的。

你才25K而已。上。嗯咋说我给你看几个吧,就这种掌新的啊。嗯。是。这是3540万年薪干到70万的,这是大龄了吧嗯。诶。涨薪的睡前睡前34干到睡前50了。一个月从新水2从20干到29的。

半年薪水涨50%了,大四没读完,就干了21K的offer。经过学习5薪水翻5倍,这就是刚才我说那个俩月年薪涨了5万的。Yeah。其准offer已经在手又收获另外一个offer的。好。嗯。

一个月干到陆金所60万年薪。美团啊涨了13万年薪。学了一个半月,拿来7个offer的。涨了8K的。我需要看你背景,这哥们儿30岁,原来从平安干到腾讯60万年薪,薪是翻倍了。

原来平安30万年薪干到腾讯60万。刚到美团薪水涨了7万的。这比较典型,哥们是国企的。国企的。总体有半年,在实际当中呢,没有俩月吧,每天晚上2到3个小时,薪水涨了20%。本他没跳槽,在原公司长的很牛啦。

这国企幅度也可以了,从基层到集团。是我们课程质量还是杠杠的啊,跟同事说还是嫌贵啊,嫌没时间,思想不到位,没有被生活好好毒打。我跟你说,课程超级值来就是了。

嗯。五八同城干到。呃,5K的58就是个中中小厂子啊,这个倒时也不不值当的有多么骄傲。6加2就干到了24乘15的。一个半月干了8K的。嗯。这只改了简历啊,月星就找了3K。这就是前面疫情期间了。疫情期间。

四轮进入飞猪。疫情期间进,阿里的。多个offer的跳槽到33万的。跳槽月薪4044万的。已经跳槽年薪42万的,年薪涨了15万的。你说这1万多块钱,自己想想有多值,好吧。就是你的1多块钱不是你不是你出的。

是3个月之后嗯,你的下一家接盘你的。这些场子替你出的哈。专升本的两个offer45万的。这是干紧google的北美google啊不是中国的。研究生跨两个月拿到金融录强满。好。自己看就是了啊。赵风照样。

明天有公开课吗?有呀,我们天天有公开课。老周两个逗比组团报名有优惠吗?组团必须有优惠,找丨小丨姐姐问就可以了。走开一下,错过了领书吗?没错,你错过了平凡。不过没有关系,你找个小姐姐要一本吧,我送你一本。

好不好?因为你的名字太平凡了,大家都是平凡的人。平凡的人送你平凡的路。就是路遥写的那本书叫什么来着?平凡的世界。送给平凡这个人。白嫖的到哪儿都不忘记白嫖。嗯,对你们把白嫖这件事情慢慢上升到。

让自己有体系的受到指导。同学们,你们自己好好琢磨琢磨啊,尤其是咱们白嫖党,你们呢上个拳击课啊,上个健身课啊,上打个打个羽毛球啊,你们知道那个报个雅思啊,出个国啊,报考个研,你们知道找牛逼老师来。

帮个客来来指导你一下。为什么当牵扯到你自身后半辈子整个人生发展的时候,你们就想不到。请牛逼的老师来带你吗?这个收益绝对比你考个研,过个四级出个国。这叫做长远收益。好好琢磨琢磨。自己玩儿白嫖,没关系。

一年你干完的路,在我们看来,仨月足够。你一年所花的精力很可能花在不该花的地方,我们带着多余的精力,不用你花。你的人生曲线发生质的改变。Yeah。嗯。白嫖的小同学好好好好琢磨你的。这种思维方式好不好?

就是你知道吗?就是人是怎么慢慢变成更牛叉了。我呀我在你们这个年龄的时候。也是觉着别人能帮我什么呀,我不知道,我不知道一个牛叉的带头人啊,跟一个不牛叉的带头人,他的他的一个区别之所在。

现在是深刻的意识到了。它的区别就在于,一个是风清扬,一个是乐不群。风清扬带你,你就是令狐冲,岳不群带你,你就是陆大有。区别就在于。一个能带你飞,一个只能带你爬。差别太大了啊。我希望你们。

我后来也慢慢发现,凡是能用钱解决的问题都不是大问题。凡是免费的都是最贵的。同学们,你们自己想,就我这个课你自己学自学。你就看着我们大纲,你找资料自己学习去。你知道你要花多长时间吗?

你要想达到我们3个月涨心5K的效果,没有两年没有两年,你根本干不到。你知道跟我们走仨月让你干到,剩下一年9个月,就是你涨薪的时间。高起点已经在眼前。白嫖党免费的都是在吃亏。这个你认也好,不认也好。

好好琢磨琢磨这事儿。对。Okay。当你们飘完这个没有了,你就亏大发了。Yeah。老师带你最关键的是啥?你花的这点钱买的是时间,小伙儿是效率。这是最值钱的。我也是很长很长时间之后才意识到啊。

其实免费的是最贵的。能花钱解决的问题都是最便宜的嗯。三四分钟我就不跟你们聊了,你们多多去骚扰骚扰小姐姐好不好?sor扰骚扰,小姐姐。Yeah。嗯,老师累了。😔,聊了聊了,反正就是挽就一个算一个了。

最关键是一个那年咋就能不玩命学吗?不需要你玩命,你就但你听话就行,还是那句话老师会给你安排好的,这周学这个下周学那个。告诉你学习方法怎么学。这么迟了也不让小姐睡觉,小姐陪你们一小。

倒计时嗯还有30多分钟,0。5秒杀截止,赶不上一对一了,烦你倒霉。Hello。老师和逗比想现要请您吃饭,欢迎啊。可以啊,我有时间的话,完全没问题啊。我们线下沙龙跟你们说啊。

我们那个那个我我们呃不是在那个呃我进门桥这儿吗?😊,我不是在进门桥。北三环进门桥北京市北三环进门桥嗯。文教产业有R哎,不过算了,你直接在百,你直接在地图上搜嘛人民教也行就知道了。啊吧。

直接去搜一下地图上一搜就找出来了。啊们在这个位置,但是你得疫情过去啊,疫情不过去,我们还是不欢迎你到访。疫情过去之后吧。😊。

呃,我们会搞一些线下沙龙啊,分享一些技术呀,分享一些不方便的公开讲的东西啊。欢迎你过来请大家伙吃饭。欢迎欢迎热烈欢迎嗯嗯。Has in太原。卢太恩。😔,只要你走,他就到了。路太远,你要迈开脚步。😔。

我觉得马老师玩马老师没空玩,不要过来找我玩。到别江景,你过来南京玩,可以啊,我最喜欢吃。鸭血粉丝汤。南京板鸭。还有。秦淮和上那那叫什么来着?嗯,忘了哈哈就是好多道菜,每一道都是一小一小盘一小盘的那个。

😊,小龙虾就算了。狮子头盐水鸭y。饿了。琪琪老师。锅贴儿。南京大萝卜鸭胗。苏北和苏南啊好像还有互相歧视的这种成分啊,也挺好玩的。呃,移动端很多人问移动端呢一般来说移动端的技术它比较杂呃。

安卓端IOS端H5端PC端它全都不一样。所以移动端呢,你要想全精通的话呢,稍微麻烦一些。另外呢移动端是这样的,呃,要想薪水拿的高啊,4万也就差不多到头了。呃,它跟服务端比呢,就是还是天花板稍低。

服务端呢到架构师呢,它薪水还是非常高的啊。呃,移但是移动端呢确实也是一个刚需。如果你不太在乎说说我三四万薪水,我认了移动端也是一个很好的选择。老师有fluer吗?必须的要啊,大哥。

南京白菊比郭德纲的先生还搞笑,真的吗?😊,哦,11点半了,小伙伴们。还有。半小时你们去骚扰骚扰小姐姐好不好?嗯,我们明天还有课,明天也可以大家继续听。是啊。Tomatomato。诶为。

系列 4:P18:【JVM大厂面试真题】对象在内存中的存储布局?(对象与数组的存储不同) - 马士兵北京中心 - BV1VP411i7E4

今天呢我们来讲这个呃111个关于职业VM的一系列的问题。这一类问题呢比较难,非常的难。呃,如果你没有听过或者没有接触过,基本你答出来可能性呢很低。看这里。现在的大厂的很多问题,他会他会追着你一问到底。

嗯,还有很多同学说我现在开始问那个原码机的内容了。对,这个很很正常也很正常啊。呃,原码的课呢我们讲的也非常的多了,深入的级别呢会讲到lininux内核的源码。那么软一点的,你像JDK的一些个源码呢。

肯定是要讲到的AQS啦啊等等这些好,不废话。呃,我们来看这个关于JVM的呃原来问到的这个7个问题啊,这7个问题是什么呢?他实际上就围绕着这句话来完成就这么简单的一句话。

这句话大家伙一看呢都能知道是什么意思。但是围绕这句话所诞生的7个问题,你就未必能回答的出来。😊,在这里。他是这么来问,他说第一个请你解释一下对象的创建过程。对象的创建过程是不是就是你扭出这个对象来。

中间执行了有哪些过程?😊,好,第二一个呢叫做DCL要DCL要不要加volatile。这里是关于指令重排序的问题,同时也涉及到多线程的问题啊,同步的问题。那么第三个问题呢。

是在对象在内存之中的存储布局到底长什么样?什么意思?我们扭出这个对象来的时候,它在内存里面到底长什么样?好,第41个对象头呢主要具体包括什么?当你明白对象在内存中存储布局的时候。

你就知道对象里面有一个东西叫对象头,到底包括什么?好,第51个对象该怎么定位,是直接还是间接。第61个呢是对象怎么分配。第七1个呢是在内存中占有多少个字节?呃,后来又他们内部在问问题的时候。

又加了两个更加深入一点的问题啊。第八个问题叫做。为什么hosport不使用C加加对象来代表ja对象?当然这个东西就涉及到一些hospot源码了,会稍微更难一些。

C加加大家都知道hosport是C加加写的。M那为什么不用C加加对象,直接来代表招务对象呢?😊,而是要采用那种OOP class2元模型。我先跟大家说一下hopot里面采用的是这种模型来代代表招就行。

叫OOP class。OOP class2元模型。好,第九个问题第九个问题是。class想到底是在堆啊,还是在方法区?呃,关于这9个问题,有多少同学能够感觉到答不出来的,你给老师扣个2,嗯。

我来认证一下。嗯。好,我今天呢给大家把这些问题讲清楚。由于内容比较多,大家认真听。我预计。哦,不一定是按照顺序来。好,现在开始。看这里我我先把这个题啊这样啊,我先把这题。先来给大家伙。😔,复制一下。

一会儿呢我们边看着题,我们边来回答问题啊,我们先看第一个问题。第一个问题我先回答家回答大家伙这个问题。就是对象在内存中的存储布局到底长什么样?呃,这个呢我就不卖关子了。我们直接呢。来看啊。

就是扭出一个对象来的时候,这个对象在内内存之中的存储布局到底长什么样?注意看一个普通对象扭一个对象。平时我们这个课程里都这么讲说扭一个对象来的时候,这个对象呢是往堆里头这么一扔啊。

画一个方块表示一个对象。但实际上大家都知道一个对象来说,就是一连串的010101。好,这些01里面每一个东西到底代表的什么意思。他问的是这个东西。认真听。作为一个普通对象来讲。可以说它分成四部分。

这四部分呢第一部分叫mark word。第二部分叫类型指针,也叫class pointer。好,第三一部分叫instance data,第四一部分呢叫对齐。为了让大家深刻的认识。这个东西。来,听我说。

我把这部分抓下来。我们来写一个程序来认知它。柯刘林。呃,这程序呢需要用到一个小小的内库,这个内裤的全称叫JOLJOL呢我我在这里就不多做解释了啊。JOL的这个内裤非常的简单,你百度一下。

花5分钟就能了解它怎么用。他的全称叫java。Object layout。Object。lay layout的布局的意思,java对象的布局。通过这样一个内库。

我可会很简单的很直接的了解到一个java的对象在它内部到底是怎么表示的。好,看这里。我先把多余的乱七八糟代码呢给大家伙删掉。全么管他。啊,现在呢我们有一个非常简单的class。

这class叫T什么都没有,就叫T。😊,那好。当我们另有一个T对象出来的时候,它的内存布局到底长什么样,一句话就可以搞定它。😡,怎么把它搞定呢?这样来做。Class layout。

这是我们JOL内库里面用到的一个类class layout out点pass instance静态方法,解析对象解析哪个对象呢?解析T这个对象to print转转成可以打印的字符串类型。

那么呃我们先把这小程序跑一下啊,就是我拗了一个T对象。下面这句话呢对它进行了T对象进行了一个分析输出,就这个意思。很简单。往边看。好了。在这里。对照我们刚才这张图啊啊。队照,我们刚才这张图放在这个位置。

呃,对于刚才这张图来说,这里头的010101,这就是我们念出来那个对象的真正的内容啊这个。

这个就是我们扭出来那个对象里面,在内存里面的0101的布局。当然每8位代表一个字节,每8位代表一个字节。那么大家可以数一下啊,说这个对象呢哎到底是。😊。

呃,占了呃多少个字节呢?如果按01来看的话,就12341行4个三行,一共12个字节。但是呢我们对照我们整个的刚才我们所说的这个对象的布局。第一部分呢叫mark word。

请大家记住mark word呢占8个字节。这里头是八字节。这个。好,第二个呢叫类型指针,类型指针指的是哎,我扭出来这个对象到底是属于哪个类。你可以认为这里有一个指针,它会指向谁?指向T点class。

因为我们拗的是T对象嘛,这不是扭的T吗?扭的T对象。所以呢通过这个指针可以找到这个class这个占多少呢?这个占4个字点。😊,好,第三一部分叫实例数据,实力数据指的什么呢?T这个对象的。他的成员变量。

比方说他内部有一个小M,好这小M扔哪扔在了这里。好,第四一部分叫对齐,对齐什么概念?整个对象的大小不能被八整除,补齐能被八整除。就这个意思。好,我们按这个规律来看,现在的这个输出,看大家是不是能看懂了。

首先我刚才说过啊。😊,mark world占多少个字节?😡,8个字节对吧?从第0个到第四个字节,从第四个到第四个字节啊,往后再数4个,一共8个字节这里。😊,对应的马克尔。好。

下面这四个字节对应的什么东西呢?对应的是class pointer。那有同学说没有实例数据。对,因为T类型它没有成员变量。好,最后叫对齐。因为这里是8个,这里是4个,加起来12个,不能被八整除。

所以最后又补了4个字节,所以一共加起来这个对象的大小是instanceize16个字节。啊,这会儿能跟上的给老师扣个一。因为我觉得比较简单,怕同学们有的认为比较复杂的啊。嗯。可以是吧,good不错。

那有同学说老师,那那那那我要是那个我要往里头装点装点那个成员变量呢,来我问大家一句。如果按照我们刚才的这个说法。我要我要我要往里头装这么一个成员变量,intM来告诉我一下,整个对象到底占多少个字节。

算一下。啊,为什么是十6呢?啊,有时候十6有时候4,有时候24的,我们先再跑一遍。😊,run。好,看这里一共还是16个字节,哎,为什么呢?前面的12个字节不变。

分别是8个字节的mark word加4个字节的class pointer。最后呢我们有一个int类型的变量,in类型。占多少个字节呢?占4个字节是吧?所以最后加起来16个字节,由于已经被能够被八整除了。

所以没有补齐了。😊,一共这么多。好,我再问大家一句。如果我这么写。Long。来告诉我整个对象多少个字间。😊,这看来家能答对吗?long是等8个字节。对。16加824个对吧?这个是没问题的,跑一下。

来看这里24个字节。我怎么没太懂你哪儿没懂啊,我怎觉得讲的算比较简单了。来告诉我这个。😊,这个对象再来一遍。多少个字节呢?不玩类型。好,跑一下看我们看多少个字节。波尔雷型比较有意思啊,我们看他怎么做的。

好,大家看这里啊,这个布尔类型占了多少个字节啊,占了一个字节。😊,所以最后给你补了7个字己。补到8个。所以。四个字节加4个字节,一共8个字节的m word。一共4个字节的class pointer。

一共4个字节的M8个字节的long,一个字节的布尔补齐7个字节,最后加起来32个字节K。而这个呢。16S等于。hello。北京。好,告诉我多少个字典。32。323232嗯。不对吧。

那我长点一共多少个字节?😊,嗯,有没有别的答案?😊,把家看。好,看这里一共是32个字节,这时候你注意看这个布尔类型直接补补到int类型,所以补三个字节。最后这个死ring类型是一个四个字节的对象。

为什么?因为这里。不要认为当我们又出一个T对象来的时候,这个东西是存在T的对象的内部,它是在哪的呀?这个S本身是一个地址,是一个指针,对吧?它是放在这儿的。但是呢这个字符串是通过这个指针指过来的啊。

指到这里嗯。

好了。到现在为止,我觉着给你讲完这个呢,我们再来看呃。

美团问的问。

系列 4:P19:【JVM大厂面试真题】Object。= new Object( )在内存中占用多少字节? - 马士兵北京中心 - BV1VP411i7E4

看第七题,第七题能答出来了吗?obero等于6ob内存中占多少个字节?多少个?说出来。16个对嗯。好,然后对象在内存中存储布局到底长什么样?

好,把这个图给我背过就行了。八字节的mark word。没有什么王八的屁股规定,只要是64位的虚拟机,它的mark word永远都是八字节64位。Cl pointer叫类型指针,默认是压缩,它是四字节。

不压缩是八字节实例数据里边你装多少算多少,反正不管你是内补齐还是外补齐,最终都得给我补齐成背8整除。

我知道大家伙还有一些细节的疑问。但是我如果你给你解答这些疑问,我就给你讲不了剩下的问题。你们是要答疑还是要往剩下的讲?我建议我先往下讲,学东西,学框架和脉络,把框架和脉络搞定之后,再去搞这些细节。

不识庐山真面目,只缘身在此山中。如果你研究一座庐山,上来先去研究山顶上某棵树下面的蚂蚁窝。我告诉你,你跟这个庐山的整体脉络就再也没有关系了。你在你的硬盘上存了很多细碎化的芝识片。

但是你从来没有建立起来过知识体系,完蛋。你的学习效率一定会特别特别低。我们呢就是自己不仅是讲求给大家一伙儿讲知识,知识这玩意儿比较简单,同时呢也教大家怎么样学习方法。同时呢给大家做一对一的规划。

所以到现在为止,我直接告诉大家,我们课程在不仅是在学生的认可了,现在是呃业界也开始认可我们的课程。

这是我们最近啊刚刚。8月30,他是去年8月31号报的名,因为他中间好多事,中间没学。球球报个喜,刚面了京东哪个部门?当场直接过面试官问我从哪学的,我说马志民教面试官说啊,马志民教育知道挺出名的OK。

就这么直接,然后多建城里回答的比较好,直接就过了。知道吧。下周刚通过,还没具体啊。

嗯,还是那句话听我的,不要听你的。

你学习了这么长时间,效率为什么低?因为你没听我的。

系列 4:P2:【JVM调优实战】C、C++的发展史 - 马士兵北京中心 - BV1VP411i7E4

呃,所以所有的程序啊最难调试的bug基本上就这两个,这是最难调试,一个叫野指针一个叫并发问题。可以这么说,在最开始的语言的发展的历史上,都是沿着对这种bug来来来更加容易调试的这个方向不断发展。

像原来C和CR加的话,大家应该知道这种是什么是是怎么怎么管理这块内存啊,怎么管理这个指针的呀,叫手工吧,手工管理。不知道有多少同学是学过C或者是CI加的。有没有有的话,老师扣个一来。

CBI里面分怎么分配一波内存?memory allocation对吧?当然它有好多好多函数都可以分配啊。这其中一个memory allocation的意思我就是开始哎在我们的内存空间里面找了块内存。

但是你总得释放它呀,你怎么释放?😊,free这个函数就可以把它给释放了。但是我告诉你啊,也许因为程序里面充满了各种各样的分支循环啊,各种各样的不同的岔路,它并不是说只有一条路线,所以只有一条路线。

或就简单了。我这边分呃mem allocation完了之后呢,后面马上就把它fr掉。可是在很多种情况下,我是要需要判断的。在这种情况下,我要把它删掉。在另外一种情况下,我不要把它删掉。我告诉你。

这就造成了各种各样各种各样麻烦的bug。所以手工管理内存,无论是C里面的memory allocation。或者是CI加里面的new和delete。本质上他这这这哥俩是一回事儿。这两段是一回事儿。

都是需要你进行手工管理。手工管理最麻烦的事情就是你不小心忘了删了,你知道吧?这空间你分配好了,但是你不小心给忘了,你把它给忘忘在这儿了,这时候会会承认什么?告诉我一下。忘记删除。忘记释放。这个呢叫。

Memory leak。这叫内存泄露,不要不要叫内存移出。大哥,它没有移出,它只是泄露了。泄露什么概念?泄露的意思就是这块空间呢虽然说留在这里,但是所有任何其他的程序不能去访问它了。不能使用它。

他留在这儿,他没用了,但是别人也不能用,这就叫泄露了。如果泄漏越来越多,会发生什么?泄露的越来越多。泄露越来越多会发生一种现象,就是当新的内存空间要申请的时候来了,我我需要申请这么大一块。

我突然间发现这里面充满了一个一个洞一个一个洞,而且中间我找不到一块连续的内存。来为我这块内存分配空间了,完蛋。这个叫内存溢出。泄露过多的时候容易产生内存溢出,但它本身不叫内存溢出。

All to memory。当然这种呢还算是不是不是很严重啊,大不了我重启一下是吧?你又能跑好长好长时间。所以调优JVM调优最重要的一点叫做重启。每两周重启一次。玩过游戏吗?有的游戏是不是就这样?

各位指挥官,我们的游戏服务器将在5分钟之后启动进行维护,在此期间不得互相攻击。good,你们已经学会了第一种。调优的。常用的方式。当然你不能跟面试官这么说,左右调优嘛。

做过怎么做到重启面试官一个大嘴巴子给你抽上来,哪凉快哪待着去。这是第一种有可能会产生问题的地方,叫忘记是吧?第二种是什么?第二种叫做。释放多次。就是你释放了一次,你delete了它的一次。

由于有分支判断各种各种方面的情况存在,也许有可能你free了好多次,delete了好多次。这个有同学说没问题啊,这块空间我不是干掉他一次,没关系啊,我再干他一次吗?不就是尸体让我又干了他一次吗?

编尸而已。没错,你只是编了个诗的,问题倒是不是特别大。但关键是当你干见他第一次的时候,有另外一个人已经把这块空间给重用了。人家已经又放上有用的空间了,结果呢你第二次回来又把人这个有用的数据给干掉了。

结果另外一个县城。就会发现莫名其妙的,你发现没有?莫名其妙的你的数据就没了。所以这是为什么说我们多线程这种bug特别难调的原因就在这里,你的线程好好的没bug,你懂吗?甚至说你的进程啊。

如果是在进程之间共享的话,你的进程没bug。没有毛病,你的程序也没有半毛钱毛病。可是很不幸的是,由于有别人家写的bug的存在,他会很容易的把你占有的这份空间给你干掉。你找谁说理去?好啦。这个叫释放多次。

产生。极其难以。极其难以调试的bug。嗯。一个县程空间。莫名其妙。被另外一个。来写过C和C加加的人,遇到过吗?遇到过的给老师扣个一。嗯。对,装装备你莫名其妙的就没了。没错。

后来呢后来啊其实谈GC呢开始聊语言的发展历史。我们我帮大家梳理一下这个语言呢,C和C加加呢它运行起来的效率非常非常的高。呃,但是呢它的开发效率很低。有的时候呢有的人呢是片面追求运行效率。但是听我说呃。

现在呢有一些大规模的软件,它并不是追求你的开并并不是追求你的你的你的运行效率有多高。也许你运行效率稍微慢一些,我拿那个硬件给你怼上去,我能接受。但是你的开发效率特别低,我就不能接受。

系列 4:P20:【JVM大厂面试真题】对象头具体包括什么?(markword klasspointer)synchronized锁信息 - 马士兵北京中心 - BV1VP411i7E4

先讲脉络,总而言之,这玩意儿它是一个死东西。这玩意儿呢如果你是64位的机器,这个mark word就是64位。如果你是1个32位的。咱们的呃GDK,那么这里就是32位啊,这是一般的那个见对象的时候啊。

做这种呃运行时对象的时候经常使用的一种技巧。看这里。在这里呢呃第二部分呢叫类型指针,类型指针比较简单,我在这就不展开了。面试的重灾区实际上在markac word这里,它的重灾区在这儿。

他说对象头者包括什么?听我说对象头这两部分。这两部分叫对像头mark word加上class point,这个叫对象头。所以当你看到呃我们这个对象布局的时候,他在前面12个字节里标了。

它叫object header叫对象头。

对象头包括8个字节的mark word,加上4个字节的class pointer,class pointer指向class的对象,这个不说了,mark word主要包括什么?这里是面试重灾区。

我直接说答案,mark word里面主要包括了三大信息。

主要包括三大信息。mark word主要包括哪三大信息?这东西没什么可说,背过就完了。第一个叫锁信息。第二个叫hsh code。第三个叫GC信息。有同学说老师我能不能看到,可以的,没问题。

我跟你讲的东西都能让你看到。

看这里。🤧我们同样是。我们同样是这个T对角。把它里边的成员变量给它注掉,就不展开了。一个小小的T对象,在个它刚刚扭出来的时候,它的布局到底长什么样?刚才我们看过了啊。看这里。刚刚溜出来这个T对象。

它的布局。他布局是这样的。好,我们说锁信息为什么是有锁信息?大家都知道啊,在JDK里面的java里面,我们想给某把某个对象当成一把锁来使用怎么做,就这么来做schronize就是把这个对象当成一把锁。

我锁定这个对象之后才可以执行里边的内容。好,我这内容里面是什么呢?再把这个T的信息输出一遍。注意这时候TB是上了锁的。为了做一个对比起间,我可以把这个锁释放了之后再做一个对比。😊,第一个是刚刚拗出来的。

第二个是上了锁的。第三个是释所释放之后的。我们来比较一下,看看哪里发生了变化。走你。仔细看,这是刚刚扭出来的时候,我们主要看那个零和一的地方就可以了。往这儿看。你会发现呢。

他第一个字节叫就是就是所有都是0,最后一个是1000001哦。😊,但是比较一下。当我们给他上了锁之后,你发现他什么长什么样啊?能看懂吗?这里明显发生了变化。好听我说,这里面记录了什么呢?

这里面记录的就是关于锁的信息。所的信息就记录在这里。我还可以告诉你,这里头你看的00,那么它就是一把轻量级锁。轻量尼锁,也就是自选锁啊。当然这里面包括了锁的升级过程,锁升级过程会从偏向锁。

到自选所到重量级锁有一个升级的过程,要看就看这两位。当然这个细节呢比较多,要要讲的话,两个小时开外去了,先把这个略过锁释放之后,你会发现okK整个对象又恢复了原来很自然的一个状态。

所以平时我们讲的时候给某某个对象来上把锁到底什么概念呢?其实就是修改了对象的m word。当然,如果你要愿意的话,你比如说我们把这个锁的信息先给它注掉,我们打开这个hsh code。

只要你对它调用了任任意一次hsh code这里面的呃布局也会产生变化。我们跑一下。看这里,这是刚刚扭出来的状态,这是调用了还是code的状态。所以这里面还是code的信息已经被我们记录在了。脑脑袋上面。

所以呢由于一个对象的hash code用的特别多,因此我们调用一个对象的hash code之后,再下次再调用的时候,都不是说重新再计算,而是直接在脑袋上拿出来就可以了啊,它效率这就是它效率高的地方。

OK有同学说,那GC的信息怎么能看到GC信息不太容易看到,因为你没有办法控制JJVM的GC的过程。但是我告诉大家GC的信息。😊,这个对象到底是什么颜色的?这个对象到底是什么颜究?

同学说老师这对象还分颜色,没错。因为一般的我们现在讲的这种GC的回收的垃圾垃圾回收算法叫什么?叫三色标记。这个对象到底什么颜色记录在哪儿?记录在我们的mark word里面。呃。

如果你听过老师的关于三色标记的课,那么你就会知道这两堂课实际上是有着有机的关联。好了。不废话了,我。😔,把刚才的这个问题啊大体上给大家介绍完了,就是对像头里面主要包括什么呀?

主要就包括mark wordclass pointer这两部分,mark word是八字节class pointer四个字节。

呃,那mark word里面主要包括什么呀?mark word里面主要包括锁信息还是code以及什么呀?GC的信息。😊,好了,这会儿还能跟上呢,给老师扣个一。神经蛙java中也是三字标记吗?

是java最开始的三次标记,其他的勾浪是后来学的。

嗯。好嘞,那我们继续。

现在呢我们回答了两个问题。第七题和第三题和第四题啊,一共回答了三个问题。好。😊。

系列 4:P21:【JVM大厂面试真题】对象怎么定位?(直接间接) - 马士兵北京中心 - BV1VP411i7E4

对象怎么定位的问题?嗯,这定位问题呢相对比较简单一些。我先讲简单的,再讲复杂的,好不好?好,我们来看这个对象怎么定位这个问题。对象定位问题指的是什么?但定位问题呢嗯。

相对复杂一些,就这玩意儿呢其实是设计JVM的人才会考虑这些问题。这个问题呢问的并不多。不过呢我建议大家还是要大致了解一下对象怎么定位。我们简单说两种方式。第一种呢叫直接定位。第二种叫间接定位。

什么叫定位定位指的是什么?定位指的是这个意思。认真听我写了这么一个一句话,str S等于new string。大家都知道我们6个str在对对里面啊,你一个对象出来,这个没有问题。

那str S是通过这个S怎么找到对应的对象,这个就叫对象的定位,就是通过这个引用是怎么找到它的,这个叫做对象的定位。仔细丁认真听设计JVM的人,其实上有两种方式来对一个对象来进行定位。哪两种呢?

第一种叫直接定位,第二种叫间接定位。当然他有一些专业名词叫直接指针或者聚柄。不管它总而言之,一个是直接,一个是间接。我们JVMhospot默认使用的就是这种直接定位。通过它呃某个算法也好。

或者直接内存地址也好,当然这里不是内直接内存地址,从某某个算法攻击会找到直接定位这个对象,已经知道这个对象的大小,已经知道这个对象的起始地址。那么这个对象就很就很容易就被定位了嘛。😊。

内存里面一大堆的零和一,我知道得从这儿开始,然后多长就结束了。那这个对象我是不是一下就找到了,就这个定位的意思。好,当然我刚我们刚才分析过了啊,说这个对象里面呢,除了包括他自己的成员变量之外呢。

还包括了什么呢?类型的指针。类型指针是通过这个指针可以找到哎,你到底是属于哪个class。😊,所以堆里面有一个对象,通过一个指针可以找到方法区里面的T点 class大概就是这个意思。这是我们。呃。

hospot默认的一种方式。除了这种方式之外呢,其实还有另外一种。另外一种呢叫聚柄方式,也叫间接的方式。间接的方式指的是什么呢?是通过哎这个指针啊直接指到了。这么一个结构体,这结构体呢。

通过这里是两个指针啊,这个指针才会找到对应的这个对象。有另外一个单独的指针指向的是这个D点class。好,这两种方式,我通过这个图相信一演示你就能演示到位了,是吧嗯。😊,好了。

那个呃我我这块呢我就先不做细节上的解释,我看看大家伙能不能接受啊,就这块大家能跟上吧,这两种方式应该都明确什么意思了,对不对?😊,来能够明确的可以继续的给老师扣个一。嗯。ossal的不明不明白不明白。

直接提问,哪不明白是吧嗯。元旦楼人啊,不明白,直接提问哪不明白。如果大家伙呢是java的小白呃,这么跟你说,薪水拿在1万到2万之间,现在还不是。没有没没有什么没有什么基础的啊,甚至说还没有就业的这些呃。

今天这课你听着会稍微费劲点,听到哪就算了,好不好?嗯。好。听我说。当然你给他讲明白对象怎么定位之后,他一定会问你哎,为什么没有采用这样的方式呢?为什么不采用间接的方式呢?间接的方式有什么好处。

有什么坏处,直接的方式有什么好处,有什么坏处,这个大家能想通吗?嗯。直接的方式有什么好处啊?快一下就定位了,光机一下就找到了,对不对?😊,好,那间接的方式有什么有有什么好处啊?😊。

鉴接的方式你发现没好处,你发现没有?你要找两次才能定位到这个对象,他不是速度很慢吗?他有什么好处呢?以前有同学告诉我说老师间接的方式。省空间。你看这个这个对象变小了,因为它里面没有这个类型的指针。😡。

同学们是这样吗?思考一下。当场不会只问你是什么,他一定会问你为什么。嗯。好,我还有同学呢回答到了问题的关键,能回答出这个问题来的人,说明是平时经过呃思考的,而且是平时注意积累了。积累了很多知识的啊。

这个真不错啊。以前我讲这个课的时候,基本上一个同学都答不出来。现在呢你看啊先生你好,说对象在内存中移动的位置,不用重新定位。对,说的非常的对。😊,就是如果是这种方式。

那么如果这个对象在内存之中移动了位置,挪到这个地方来了。同学们,你想一下,你这个T里面的所包含的这个地址要不要跟着变?啊,你从503挪到了806楼层都挪了,你说这里的地址。变不变,务必跟着变,肯定得变。

但是这种方式就不用这个对象挪过去了。没关系,这个T不用变T不用变所带来的好处是什么?垃圾回收。效率就会比较高。有同学说老师这事儿不对呀,有这个垃圾回收这玩意儿。😡,为什么会挪动地址呀?好。

这块就会涉及到JVM垃圾回收的它的一个过程。作为这边M来说,最普通的叫做分带模型。现在用的最新的叫分区模型。不管是分带模型还是分区模型,内存呢一定会从一个。对象会从内存中的一个位置挪到另外一个位置。

它一旦挪动,你的这个指针必须跟着变。好了,大概就是这个意思啊,在这儿呢我就不多说了。因为不知道,因为有很多很多同学呢,可能连呃这班的垃圾回收到底什么样,不知道。呃,尤其是我给大家讲这个什么叫分带模型啊。

什么东西又叫分区模型。我讲这些东西的时候啊,如果没有一定的基础,应该是听不太懂。所以呢我就在这不展开了。呃,这个题呢无所谓的事儿,因为这个题问的也非常的少,把它放过。所以到现在为止呢。

我们大概讲了这么几道题。

系列 4:P22:【JVM大厂面试真题】对象怎么分配?(栈上-线程本地- Eden-0ld) - 马士兵北京中心 - BV1VP411i7E4

来看第六个第六个问题叫做对象怎么分配。认真定。现在这些题都相对简单,所以我过的速度非常快。居名指向的地址不是也得变吗?你说的很对,但是呢它内部。will啊,我解答唯唯一解答will的一个问题。

就是聚丙指行的地址不是也得变,是得变。但是它内部对于对象的整个维护。这个对象要不要回收啊,到什么维呃就是回收到什么程度了,他是把那个指针来用那个T那个指针来维护的那个指针只要不变的话。

它计算的效率就高很多很多嗯。好了。嗯。如果你你你如果想深入了解,可以了解一下那个三色标记算法。你会发现呢,在三色标记算法里面还有挪动的时候,整个是需要维护它的什么呢?维护它的内存的地址必须得维护出来。

如果他来回来去老变。那个维护你你的那个ha是扣的表,哈西表就必须老跟着编。在这不展开了。我们谈这个啊叫对象怎么分配。这过程我希望大家伙把它背过。有很多比较复杂的过程呢,我一般喜欢做动画。

这是为什么我喜欢用PPT的原因。很多人喜欢画图也好,或者还喜欢用文字也好,无论怎么样,也不可能用动画描述的,像我用动画描述的更加精确,不信你就仔细看。好,看这里。对象怎么分配?哎呀,我的天哪。

我发现我我我最后再回答一个问题啊,我最后再回答一个问题。这个问题之后,我们开始讲对象怎么分配。因为每次讲到这儿呢,因为同学们。😊,呃,对于这个问题的疑问会比较多一些。

我稍微多讲两句就看这里神经蛙问了个问题,他说垃圾会收不是在堆上,T不是在站上吗?譬我就想问你,我写了这么一句话,叫stream S等于new string。我想问你这个S一定是在占着吗?一定是在站上吗?

哪位同学告诉我。😡,S等于new string,这个S一定在站吗?你这个S不能是一个对象里面的成员变量啊,大哥。你拿大腿给我想想,沈建华这么简单的问题跟这。有疑问是不是?好了,不废话了。

来看这里看对象怎么分配啊,这个过程也比较复杂。😊,对象怎么分配?有同学可能会说了,大哥那个对象分配,那还不简单,直接扭个对象往对象一扔嘛,很简单嘛,对不对嗯。😊,我看刚才有同学说声音忽高忽低。

有多少同学有这个问题,有这个问题的给老师扣1。声音无靠无的,就是头讯课堂这个。就是腾讯可堂做的这玩意儿吧,我说有的时候真是无语啊。我已经把降噪给关了。嗯,自动争议给它关掉,回音消除给它关掉。降噪开成弱。

喂,hello,好点吗?😊,好点了吗?更不行了。呃,如果是更不行了,你就把你那边的声音啊那个稍微开大点。但是呢声音有点小,你可以把你那边的功放开大点,好吗?他就是忽高忽低会比较难受。声音小。

你可以把你的功放开大啊。哎,来看这里,我们来看这个对象怎么分配的问题。这个问题呢,基本上也是一一系列的JVM的一个总结性的,你才能够了解的理解得了。大家伙认真听。

这里头的分配指的是JDK默认的垃截回收器。呃,这JVM一共有10种垃圾回收器。这10种呢分别是sal serialal old, parallel parallelel old。CMS然后呢。

parelve啊,这个G oneCDCsando和eppsilon一共有10种。在JDK的1。8,这是大家伙经常使用的一个版本。线上呢大多数用的都是这个版本。GDK的1。8。

它默认使用的垃圾回收器叫做PS加POparlocar加 parallello old好,细节我们不展开这个垃圾回收器会把对象分成啊,会把内存分成两部分,一一般我们称之为叫分区模型。

这个分区模型呢分成两部分,这两部分分别叫做第一部分叫年轻贷。第二部分叫老年代。那么整个对象呢会在年轻代和老年代之间的来回复制。好了,同学们。嗯,我刚才讲的这一小段来能跟上的给老师扣个一。

这块需要我展开一下吗?需要我展开的给老师扣个6吧。如果需要我展开的。就是我刚才讲的这小段听不明白的。嗯,我讲到这儿,我我突然想起来,估计会有好多小伙伴这块跟不上。

嗯。我看这里。我告诉大家这张图。嗯。好,看这张图。这张图啊就是呃我们默使用的默认的垃截回收器。叫做分带的这种垃圾回收器,它使用的一种内存模型。这种内存模型呢会把我们的整个内存分成两部分。

这两部分分为长什么样呢?就是哎这里是新生代,新生代的意思呀,很简单,就是我们刚刚扭出来对象刚刚扭的新生儿嘛,哎放到我们的新生代里。然后呢,我们那老年代老年代在哪呢?老年代是。

经历了好多次的垃圾回收都干不掉的人。比方说这个对象扔进来了,但他一直有用垃圾回收跑一次,哎,没有把你回收掉。这个时候呢就很简单,就把你的年龄加1。来就回收又来了一次,又没把你回收掉。

加2当你到达了一定的年龄之后,进入到老。好了,这里是年轻代,这里是老年代。来,这个概念大家听明白了吗?那,能跟上的给老师扣个一。就是年轻代就是装那个新对象的,老年代呢就是装那个老对象的。😊,当然。

年轻代和老年代呢采用的算法是不一样的。垃圾回收这东西呢有好多种算法,一般来说有三种。从上个世纪五六十年代开始到现在为止,就这三种。这三种呢,第一个呢叫标记。清除就是你这里是个垃圾,哎,把你标出来。

把你干掉,把这块空间给你空出来就行。好,第二种呢叫复制。复制是什么意思呀?😡,我们先说这个标记清楚啊,标清楚也比较简单,你拿大腿想想,我把你标出来,把你清掉啊,时间一长把你标出来,把你清掉。时间一长。

我们的内存会产产生什么呢?会产生碎片化。😡,税票。又这这里有一个洞空出来了,这里有一个洞空出来了,碎片化的产生的原因产生了之后会有什么后果呢?就是当你弄一个大对象,你发现装不进去了,为什么?

因为那些个碎片化的东西加起来呃,能够被我装进去。但是呢那个碎片没连着。所以呢如果我们在标记的时候清除完了之后,再加一个整理的过程。整理的过程指的什么呀?指的是哎。

把这些个中间的这些空的东西都给它挪到一起去,把中间有用的对象全挪到前面来。哎,在标记完了之后再做个整理。这是第二种算法。这个算法呢叫标记整理或者叫标记压缩。特别简单,跟操作系统一样。对,说的很对。好。

这两种算法大家会听明白了,对不对啊,不难。好,这其中呢还有一种算法,这种算法是什么呢?叫复制。复制是什么意思?复制的意思是这样的,认真听。这是我的内存啊。甭管你多大,我给你一分为二,分成两个,特别好玩。

哎,我这个里面的这个对象呀,凡是活着的,我都给他拎出来。甭管他在哪。然后统一的复制到另外一边来。同时排列好啊,这个这个速度很快的。拿过来之后,挨着盘的复制嘛,复制过来之后,一下把整个内存全部清掉。哎。

你会发现这玩意儿的效率特别高,贼高。这是效率最高的一种呃,垃圾回收的方式,但是毛病也很大,你拿大腿想想都知道是吧啊,你你你你你你会一看。浪费空间,甭管多大内存只能用一半啊,是不是?好啦。

所以大多数的垃圾回收器都是怎么做呢?他会嗯。综合运用咱们将刚才讲的这三种方式。那么PSPO是怎么做的呢?我给大家简单解释一下,你认真听。在这里。他这么来做的。当我们刚刚调出来第一个对象的时候。好。

这个对象呢会扔到我们年轻代里面,在年轻代里面会分成3块区域。第一块区域叫伊甸园,人类诞生的地方叫伊变区。当然所有年轻的对象啊,这是诞生的地方就扔在这儿了。好。呃,一般来说。

这种年轻的对象呢特别容易被回收。呃,这个大多数程序的一个统计呢,你你比方说你一次性产生100个对象,经过一次垃圾回收,很有可能会回收掉95个,知道吧?只有5个是活着的。如果这事你理解不了。

你就想一个fer循环里面,你不停的扭对象。这个出了这份循环,没有人认识他他他就会成为垃圾了,就很简单一件事。同学们,你就想了,如果说100个对象会被回收掉95个。那采用什么样的算法效率最高呢?

当然是复制,你想想一定是复制啊,对不对?那个呃复制算法为什么效率高呀?因为它只有5个活着的,你只用把这5个哎给复制到另外一一块区域里头去,是不是就可以了?😊,所以年轻贷里面采用的算法叫做复制算法。

但是这个复制如果说你把年轻贷一分为二,浪费空间浪费的太多了。尤其是你想想我要复制过来的这块空间,只有5个对象。我用得着那么大一块空间吗?用不着。所以这个时候他的算法是怎么做的,是这么来做的。

这里产生一个对象。然后如果经过垃圾回收,它还活着,它会被复制到另外一块区域里。这块区域叫做surviver,叫幸存者。S0S1S1S2from to说的都是这块区域,不管它叫什么名词,无所谓。总而言之。

复制到一块相对小的区域里,为什么它小就可以?因为他活着对象很少。好,这块还能跟上的,给老师扣个音,我我会认我认为比较简单,对你来说未必未必简单啊。就是它的中间的设计为什么这么来设计?就在于这儿。

你会发现呢它的80%的区域,年轻年轻在里面80%的区域都叫一甸源区。10%是死歪玩区。另外的10%是另外一个40本K。他这么来做的。ok。那有同学会说了,那为什么需要两个sver啊?很简单。

因为还他除了经历这次复制之外,还要经历下一次复制,什么意思?看这里。这是我们这个对象。比如说我们整个对象啊,用了5个对象出来,然后一次回收干掉了4个。

只剩了一个活着的这一个活着的会被我们复制到一个sve里面。接下来把整个一甸园去全部干掉,他又可以重新使用了,特别爽,连连续的你可以分配好多对象一次性的。后来又来了5个对象。然后呢,又被干掉了4个。

只剩一个活着的。同学们,你们想一下,我下次再回收的时候,我是不是连这个都想得一块回收?如果这个对象被回收了,他们会不会被干掉。如果这个对象不会被回收,注意你还能往自己的这个里面来复制吗?你没法复制了。

你得去哪复制呢?你得把这两个活着对象都复制到。哎,第二个svivver,接下来把这个和这个一块干掉。下一次再开始的时候呢,把这个活着的又复制回来。然后呢,把这个和这个一块干掉,你会发现这2块区域。

同时使用的只有一块浪费的空又多少,只有10%而已。不像原来一分为2,浪费50%。来这块儿能听明白的给老师扣个一。对,默认比例811,但实际上JVM的调优,我们讲JVM调优是什么东西?

JVM调优就是可以调整这些比例关系。比说年轻代默认比例对跟老年代1比2。但如果说你那个呃你本身你的算法产生的年轻的东西比较多,老年的东西比较少。这个很简单,你就改成2比1都没关系,随便你。好了。

能听明白的。如果还没听明白,我给你一个动画看。仔细看一个对象从出生到消亡的过程,他到底长什么样?你有这个对象最开始产生放在站上。当然这个先略过,这是一个细节,这个先略过,他会首先进入到伊甸园区。

进入到伊甸园区之后呢,如果他还活着。复制到S1。如果下次还活着,被经历一次垃圾回收之后,还活着复制到S2。还活着又复制回来还活着又复制回来,一直到年龄够了,进入到老年代为止。当然。

老年的表他又被回收掉了,那说明什么他就被被干掉了。就结束了,从出生到销亡,大概是这么一个过程。好。这会儿还能跟上呢,给老师扣个一哎,可以可以继续的。所以下面呢我我就给大家伙补一点这个知识啊。

下面我来讲对象怎么分配这过程。这过程是这样的,仔细听认真听。当你刚刚开始另一个对象的时候,首先会尝试在站上分配。有同学说了,老师一一直一直您讲的就是在堆上分配啊。你你去问哪个线下的老师,你随便学。

他说的6一个对象一定是往堆上分。对,是的,但是很不幸的是,如果你的被大肠问到。你就必须把这个过程给他说出来。你有一个对象的时候,首先会尝试往站上分配。有同学可能就会说大哥还能往站上分配。这是什么概念?

这是一个站,站里面通常有方法的调用过程。好,这是一个main方法。关于ma方法的局部变量,全往这都,能听懂吗?比方说我在ma里面声明了一个。变量int类型M等于8。好,这是放在妹方法里面的一条语句。

这个东西叫ma方法的局部变量,它局部变量。放在站里面,所以这个小M等于八就扔在这儿。接下来第二一个呢,如果这个ma方法调用了另外一个方法啊,第二个方法叫Mma方法执行到这儿了,还没开始继续执行的时候。

就调用了另外一个方法。这个方法进入到站里面。好,这是这个方法,自己局不样论的空间。这个一般我们称之为叫战争,叫tack frame。好,不管它。这个方法又调落第三个方法,没关系啊,再进来。好。仔细听。

当我们明白了这个过程之后,一个方法一旦结束了。你比方说这是M方法,这是N方法。M调用了NN结束了,回到了M继续往M往下执行了。同学们告诉我一下,这个里面怎么处理呢?这里面有操作系统,直接来帮我们管理。

直接把它往外一弹。什么叫往外一弹,站顶指针往下一挪,这块空间就废了。好了,这个叫做。战大家明白了什么叫做战的或者叫战争的概念之后,你会发现呢,如果用战争来搞管理对象。

这里面对象呢放在这里有一个什么好处啊,好处就在于,只要这个战争一结束。帮机往外一弹。我们的对象自然而然就结束了。我需要垃圾回收来参与吗?不需要。效率高高,太高了,垃圾回收这个玩意儿是一个。

咱们系统里面的现程知道吧?需要这个县程定期的或者找时间来运行,你才能够把这个对象给回收掉。但是如果你的对象放在站里面,你会发现。😊,不需要他参与。直接往外一弹结束。所以当你一个对象可以分配在站上的时候。

有什么好处呢?好处就在于。网站上一分配。这样往外一谈,哎,整个对象分配结束。在,这会儿能听懂的给老师扣个一。当然。那你明确了这件事之后,你一定会问,那为什么不是所有对象全都分配在站上啊,有这个疑问吗?

😡,肯定有这个疑问。为什么不是所有对象全部分别在站上?😡,听我说站上这东西,其实呢嗯。是因为什么呢?站上这东西呃。看刚才有朋友,我看刚才同学跟那说热热预热默认,不管他啊,听我说站上这东西。

第一个占的空间比较小,默认是256K,知道吗?就这么大个。所以经常我们遇到tack overflow叫粘移出。如果你对象全部在上面被移出了,还有一个。有些对象不能往站上分,为什么?

比如说给你举个最简单的例子,这是一个战争。它里面有个引用,用到了这里面的一个对象。你这玩意儿能随便谈吗?你往外一弹的话,你好好琢磨琢磨。😡,我这里面的引用是不是就孔指针错了,你谈完了,我找不着那对象了。

你不就孔指针了吗?所以这里面呢,站上分配是需要有两个标准的。第一个标准呢叫做逃逸分析。逃逸分析的意思就是说,我看你有没有逃出我整个方法的执行范围。比方说你for循环里面,别人谁也没用到的对象。

你可以往站上分,完全没有问题。但是如果这对象被别的方法里面的引用给用到了,或者被堆里面的某个。引用给用到了,那你完蛋绝对不可能往这样分配的。因为你这个这样一谈,别的引用就完蛋了,就用不用用不了你了。

所以这叫逃逸分析,看看你的生存有没有逃出我们整个的方法范围。好,第二个叫标量替换,我就不解释了,只能用最基础的数据类型才能够。能够替代的对象才能够往这这上面分配。你说特别复杂的,有些引用类型放在上面。

不好意思,这上面不能分。好,不废话了,了解这个过程就可以。来,可以继续的给老师扣个一。😊,嗯。好对象怎么分配,这是第这是第一个一个过程。第二过程是什么样的?如果在站上分配不下,就看这个对象是不是个够大。

如果是一个特别大的对象,我告诉你直接进入老年代old old区老年代。当然老年代的话是需要经过负DC叫做全量回收啊。负DC之后才会被回收回收掉。哎有同学马上就会问。老师这个个够够不够大,是什么意思?

多大是大,听我说JVM调U里面,你完全可以用一个参数来控制,叫max threshold。我在这就不展开了。那现在真的有对象在这样分配吗?这不是废话吗?我给你讲半天了,哎,不就给你讲。在这上分配吗?

其实我是可以向你证明的,我只是懒得给你证明了而已。嗯,占赏分配。罗鸟愿意把这小东西拿走。而且呢把这些个参数都给我打开或者关闭。仔细实验一下,你就会知道哦,确实有战赏分配这个概念。不展开了好吧。

可以不展开吗嗯。😊,来可以,同学给老师扣一,我们继续不可以,同学给老师扣7652。63的开根号,最后得到的结果值。OK大家伙都觉得都可以,那我们继续啊。😊,嗯。开个玩笑啊,看你们有没有在认真听课嗯。😊。

啊,看这里啊。嗯,他因为因为因为这东西呢细节太多,他有好几个参数,像他必须你要把他的战役战译出给他关掉的话,怎么怎么做呢?就是逃逸分析给他关掉要 escape analysis做逃逸分析。

你必须得把这参数给他关掉。还有一个呢必须关掉标量替换。还有一个呢必须得关掉 buffer这个我一会讲给你听。

OK看这里。好,接下来我们刚才说他个儿够大,直接就进入到老年代了。那他不大不小,又不能在站上分配,这时候分配在哪呢?这时候才会正式的进入到我们刚才讲的那个过程。接入到哪儿去呢?进入到了。

伊甸园区伊甸区啊,回想我刚才给你讲那张图。好了,但是有同学马上说说老师怎么前面还有一步啊,对,这步叫做尝试在县城本地分配。什么意思?这个T2AB的全称。他是这几个单词的缩写。

thread现场local本地。呃了。Ocaion分 buffer。缓冲区叫县城本地分配缓冲区叫。请跟我读跟着我读re local allocation buffer。要读出那种英国流氓英了啊。

relic allocation bug。There没 logo allegation about that。23的口音也可以。我要不开玩笑了,就是县城本地分配,这到底是什么意思?认真听。如果说我们。

呃,一个程序开始之后,好多个现场。开始往那个伊甸园区开始分配对象,注意是好多个县程。那么大家想一下,你如果想分配好这个对象的话,必须得做现程同步。大家伙都看上这个位置了,谁抢到算谁的。

各个县城之间的同步必须得做好做到位才可以。这点很容易理解。但是如果上来就给县城做同步,这个效率一定高不了。所以呢它在前面加了这么一步优化,这个优化指的是什么呢?给每个县城一块独立的空间,什么意思?

每一个小县城在一甸园区里面啊,都有自己的一块独立的空间啊,这是A县程的空间,这是B县程的空间。A县城要分配对象的时候,优先往自己兜里装。😊,B县城优先往自己兜里装,不会先用公共区域,先在自己的卧室啊。

往往往里装,只有卧室不够使了,再去那个客厅里面去抢抢位置。所以说。你自己往我自己兜里装,你还需要现程同步吗?不需要,所以这个效率就又变高了。

OK这个东西呢叫three local election buffer。如果大家感兴趣,GVM调优里面这块区域也可以调。但是这块区域本身就分配在伊甸园区。所以我们说对象。在这块区域。

不管你开没开启sloc啊,最终都是在伊甸园区进行了分配。🤧啊,这块能跟上的,可以继续的给老师扣1。嗯。这个YN代表啥?这个Y叫yes,这个N叫no。好。我们在这个伊甸园区。那了伊甸园区之后。

回想我们刚才执行的过程啊,这伊甸园区如果被击C,那就会说清除一遍。被清掉了,那就直接结束了。如果没有被清掉会怎么样啊?回想一下是不是进入到我们的S一去了。S一区。又经过一次垃圾回收,如果被清掉了。

那就又结束了。如果没有被清掉,就看你的年龄多大。如果年龄够了,是不是又进入到老年代了?如果年龄不够,会进入到S2去,如此的循环往复。好,抓图吧。对象怎么分配的过程,我用一张逗号给大家画出来了。

逗号我画了2小时,给他演示完5分钟。讲一门好客比较辛苦的。不是那么的容易。这张图啊。Yeah。好。现在美团的。大概有几个问题。我们现在能回答了朝燕第七个问题。

你们可以回答了objectO等于new objectject内存中占占多少个字节呢?16个。😊,对象怎么分配呢?哎,首先在这,然后在现城本地伊甸园区old区中间呢有S1S0S1互相之间的复制过程。

对象怎么定位呢?直接和间接两种方式主要是体现在垃圾回收的区别上。对象头具体包括什么呢?mark wordclass point啊, synchron。

然后mark word里面主要包括什么锁信息GC的信息。还有一个呢?还是扣的信息,对不对?对象在内存中的存储布局长什么样呢?四部分mark word。Class pointer。

instance data和padding。好,到现在为止,34567讲完了。9点06分速度还可以吗?如果说那个时间充足的话呢,我会给你讲里面的好多好多细节,时间不充裕,有些细节我先错过。

比如说class pointer本质上这玩意呢,虽然说你你你你你认为啊。class pointer这玩意儿。啊,虽然说你认为呃,他是一个一个一个。四个字节,但实际上呢。

这里面有开启压缩和不开启压缩的区别。这里面还有超过32G内存之后自动失效的区别。这里面比较复杂,我就不展开了。而不管怎么样,听我说,起码34567我能答出一大概来了,对不对?

系列 4:P23:【JVM大厂面试真题】请解释一下对象的创建过程?(半初始化) - 马士兵北京中心 - BV1VP411i7E4

好了,下面我们来聊一和2。一和二他娘的是最难的,每次讲一和二比较头疼,所以我们要留留足充裕的时间来给大家讲一和2哎。哦,可以继续的来给老师扣个一啊。😊,该进广告了,没有啊。我没有想打广告的。

我们讲第一题和第二题。一题和第二题是最复杂的,我尝试讲给你听。第一题呢叫做解释对象的创建过程。什么叫对象的创建过程?这东西呢。嗯,讲起来呢并不是并不难,我直接告诉你,我我先给你讲结论啊。

认真听对象的创建过程什么样的?其实对象创建过程比较简单,就object O等于new object。它首先往这块空间里头你有一个对象出来是吧?刚才我们说过这个对象里面内存布局了。

那它推向创建过程到底长什么样吗?得听我说对象的创建过程,实际上它是分成三部分三步构成。如果大家伙想了解一个对象的创建过程到底是哪三步,你做一个小小的操作,这个操作这么来做。这是刚才我们这个小T对象。

删掉。我们就执行一句话,T小T等于6T,其他什么都不执行。跑一下的小程序。然后接下来我们去观察这个小程序所生成的字节码。这是什么意思?就是java语言的汇编代码。class的字节码,它到底长什么样?

我们来看。怎么看vi。Show bycode。看它的生成的字节码,或者是使用一个插件。这个插件呢叫J class library。我喜欢用这个插件。

这插件叫s code with the j class library。打开来看,他会帮你把你整个生成的class文件全部帮你分析一遍。生成的方法里面类方法。在它里面的代码到底长啥样,就在这儿。嗯。

这里面有个satic class,这里面生用的稍微复杂了一些。这样啊,我把代码呢再写的再简化一些。看这里,因为这里头呢有一个interrup exception,我把代码写的再简单一些。就这么简单。

obO等于new。Oject。跑一下。好,我们再来看它生成字节码。6 should by code。With the j class slide。方法没有方法。

扣的。你看一眼他生成的字节码。

生成这个字节码呢大概是有方便手机的。大概是由55个指令构成。这第一条指令叫new new指令。缪指令是个什么概念?我先跟大家说,new就是扭一个对象。那就是分配一块空间,你会发现他掉了一个对象。

这个对象呢就是javaline object,所以他拗的是这个对象。第二条指令叫duplicate。我今天不想给大家讲,ja不到汇编码,这是在我这破里专门讲的。先把这块给大家略过,这块比较复杂。

我先把它略过。好,第四第二步第二步叫什么?第二步叫invoke specialial特 invoke调用,special特殊叫特殊调用。特殊调用了一个方法,哪个方法呢?一号方法一号方法是哪个?

是object的initialize方法,就是它的构造方法。你调一个对象,肯定要调它构造方法,对不对?好,第第三步叫做ace store a store的意思叫建立关联。我一会给你解释。好。

这条指令呢叫return returnturn就不管了。所以最核心的指令有3条,分别是new。invo special和a store。来这会儿能跟上的,给老师扣个一。

我下面向你解释这三条指令到底是个什么样的概念?我看这里。

我们解释对象的创新过程。刚才我说了6这条指令啊,就是内存里头申请一块空间。但是大家知道,如果一个对象里面有成员变量的,它的成员变量一定是要占空间的。比方说我们有这样一个classT。

它内部有一个成员变量是小M。我想问你当执行到这条指令的时候,这个小M的值是几是8吗?讲到这儿呢,有一些语言的历史,我稍微给你们展开一点点。老师我呢从最开始的时候,我们讲这个语言里面的,怎么说。

就是讲这个讲这个讲这个呃C加加语言,先还是讲C加加,后来讲汇编讲C,然后一直讲到java,讲了很多很多种语言。我原来在那个。华中科大就是。左老师的母校啊,曾经讲C加加的时候,同学们都跟那震撼,我靠。

原来C加加还能这么讲。认真听C加加语言呢,它也能扭对象。这个大家知道C语言其实也能扭对象,无非就是分配一块内存,把这个内存里面好好来组织一下就可以。但是。听我说。我想问大家一句话。

如果在C加加里面或者在C里面,当我们扭出一个对象来的时候,它里面有个成员变量小M。我想问你这个M的值最开始是几?这个大家能知道吗?如果在C加加里面扭出来一个对象int类型的这个小M的值会是几?

怎么这么多说零的呀?这都是没学过,有没有学过C加加的,跟跟我说一个。这说灵的明显是没学过的,没学过C的。这东西叫做遗留纸,遗留纸能听懂吗?什么意思?什么叫遗留值啊?遗留值的意思就很简单。

就是上次有一个程序在这里面用过了一个数值。注意我们说这块区域又可用了,他只是做个在这里做个标记,说这块区域又可以用了分配一个对象往这一分配的话,上次留下的里面的这值是几,这个M就是几,上次用完啥。

这东西就是啥?所以这是遗留值OK。你前男友的吻深深的印在了你的嘴唇上,所以你的新男友印在了你前男友的。怎么这么乱呢?我不说了啊,就是总而言之呢,它中间没有一个renew的过程。OK。

他就是一个有一个遗留值在这里,所以遗留值。就会诞生一些个安全性的问题。为什么会有安全性问题?比方说这个地儿正好是个密码。你上来之后,你M等于几,等于你的新程序可以直接访问这块内存,直接拿密码了。我的天。

😊,大家都知道那个汇编啊,C啊都能做什么东西呢?做逆向,对不对?逆向怎么做,就是分析里面的现在正在跑的那个值到底是多少,直接给他改过来。OK。正是由于这些安全性的问题。java是怎么做的呢?

Java是这么做的。当我们扭出来任何一块内存之后,它里面有个成员变量。都给他附成默认制。所以像inter类型的默认值0。波尔类型的默认值false。引用类型的默认值空。OK。

所以当我们扭出来一个对象的时候,它里面的成员变量注意是默认只是几是零,它并不是等于8的。来,这会儿能听懂的给老师扣个一。对他先清理了一下,等于你交了个新女朋友,他实际上把自己renew了一下。

把自己遗留他前男友遗留的各种各样的问题呢,都从身上清理了一遍,能听懂吗嗯。所以你得到的是一个。崭新的。女朋友或者男朋友啊,开了个玩笑啊,好不说了,所以java的比较安全啊。嗯,大概就这个意思。好。

那中间这个invo special只有调用完构造方法之后,这个值才会被我们复制成为8。原来是0,后来它就变成8。好,第三步叫A store,我来解释,看这里。第一步。

当我们执行到newnew这一步指令的时候,它里面的值0。执行到invo special的时候,这个值才会变成8。那下面这个a store的意思很简单。这个小T哎和我们这个对象建立关联。

所以对象的创建过程由三步构成。第一步,申请空间。设默认值。第二步。调构造方法设初始制第三步建立关联。好的。很简单,所以第一题也特别简单。这是。解释对象的创建过程,半初始化,这个题非常的简单。

系列 4:P24:【JVM大厂面试真题】加问DCL要不要加volatile问题?(指令重排) - 马士兵北京中心 - BV1VP411i7E4

而且就超级难。第二题太太他娘的了,每次讲这个题呢都都比较费劲,但是也没有办法不讲。先承诺给大家讲给大家听。好,听我说。要讲清楚。第二个问题,我们先来聊。一个触及灵魂的问题啊。嗯。蒋这个成序员。

需要掌握的底层知识啊。嗯。嗯嗯嗯。汇编啊。😔,嗯。

嗯。稍等啊,我还是得得要PPT给大家演示,不然的话呢,比较费劲。好,听我说啊,我们现在先问大家一个小的问题。这个问题是这样的,他说程序是真的按照顺序执行,这什么意思?真听。比如说啊我们现在有两条指令啊。

或者要两条语句吧,说X等于X加加。或者是X等一Y等于一这两条指令啊,这两这两条语句到底是一定是程序真正执行的时候,是一定是先执行它再执行它吗?一定是先执行他再执行他吗?我先说结论,结论叫做未必。

结论叫未必不一定什么意思?就是在你程序真正开始执行两条指令的时候,很有可能是后面你写的指令先执行,前面写的指令后执行。我们我们先我们先我们先记住这个结论。然后我们再来讲为什么原因呢?其实很简单。

我稍微给你解释一下,你就明白。比如说啊我们的CPU执行指令的时候,它的速度非常快,它是内存访问速度的100倍。如果我们现在有两条指令,第一条指令呢是去内存里面取个数据。

第二条指令就是CPU内部的一个加加操作,某个寄存器加了个一。那但是你想一下,如果说我们强制按照CPU按照这两条语句的顺序执行。强制按照它按照顺序,那是不是会造成这么一个现象?

就是当我的CPU执行这条指令的时候,我发了一条指令给内存,我就得等着内存大概100个时间单位之后,就我CPU在那歇着,你懂吗?等100个时间单位。嘿,等你回来了之后,我才能继续执行。第二条。

这个大家能听懂吗?就好比说我们那烧个水,想泡个茶,我烧完水,我必须等得等得等水开了,我才能去。拿茶叶洗茶壶、洗茶杯泡茶。所以。CPU怎么能容忍这样的浪费呢?所以一般来说它是可以进行优化的。

怎么进行优化呀?能进行优化优化的办法就是我烧水的时候,我同事就开始洗茶杯喜茶玩不就得了吗?所以。我在发出这条指令,等这条指令还没有回来的时候,我就开始执行下面的指令。下面的指令跨机先执行完。哎。

等什么时候这条指令回来了,我们再继续往下执行。😊,哎,这会儿能听明白的,给老师扣个一。所以在你真正开始执行程序的时候,有可能是哎后面写的程序先执行,前面写的程序后执行啊。有同学是能不能证明?

时间关系我就不给你证明了。我告诉你,我写成这个程序完全可以证明出来。嗯,VIP呢,我专门给大家写了证明,在这我就不单独写了。因为这个过程呢也相对复杂的解释半天。因为后面呢还有很多事儿要做。

所以我们先跟大家说说清楚这件事,程序不一定是按照顺序执行。当然有同学呢可能会说了,说老师这事不对呀。你想想看。像这样的两条语句能随便换顺序吗?我想问问能换吗?这肯定不能换,这换了顺序。

比方说原来的X值为0,这换了顺序,最后的结果是不对的。你先在等于X加加,最后结果是2,你先X加加最后X等于之后结果是一,这能对吗?😊,这不行。所以大家认真听我讲。程序什么时候能够乱续。

最终的一条规则叫做。保持只要保持最终一致性就可以。什么意思?注意,这里使的是单线程乱续。单纯论叙的意思是,只要在一个县城里面,这两条语句随便换,不管你怎么换,换到最后最终的结果是一样的。你看这两条语据。

我先执行Y等于和先执行X等于一最终的结果,我们内存里面是不是这块X等于一,这块I这块Y等于一,无论你怎么换,无所谓嘛。X等0Y等。Y等于2。5。随便换对不对?所以前面两条语句叫做没有产生依赖。

你就可以随便换。哎,别的人也一样。对,没错。来,待会儿能听明白的,给老师扣个一嗯。所以说程序不一定是按照顺序执行的。那到底呃什么样的东西?可以换顺序的,反正保持最终一致性就可以。

那如果我讲了这个问题之后啊,我想问大家一个小的问题。这是一道面试题,也是一道面试题啊。比这道面题稍微容易一些,我看还能不能打得出来。看这里。来看这道题。为了方便手机档,我把它复制一下,放大。

这个体贴的男人啊。呃,手机档应该也能看清,仔细看。嗯,来看着小程序,我们有一个类啊,这个类呢叫T03。😊,然后呢呃他有一个成员变量number等8。然后呃,在我们6T03的时候呢,启动一个线程。

这个线程呢是打印this点 number,让它启动。接下来呃,我们在 main方法里面new了这个对象。哎,你可以想一下,我扭完这个对象之后,一个线程启动,然后打印这个number等吧。

来告诉我一下这个程序有没有什么问题。有没有bug存在?有bug吗?好,这个程序呢叫做注名的this溢出问题啊。他叫做this escape,就就这个单这两个单词。

this escape叫this一出问题。这个就是这句话是什么意思?为什么会产生这种问题?你仔细听啊,同学们,你们回想一下,我们另一个对象是由三步构成,记得吗?六一个对象的时候。这里我们定了个对象。

第一步呢是扭了哎,扭了一半,刚刚申请完空间,这里面的number值是几啊?是0。好,我假设我刚刚扭了一半的时候,我另外一个线程启动了。另外一个县城启动了。我是不是就能读到这个中间状态啊?

这个大家能能理解吗?我这对象购的方法还没执行完呢,我这县程是不是就已经启动完了,我现程启动完了之后,OK。😊,我是不是就读到这个中间状态了,所以你读的时候,这个vis number是有可能输出为零的。

虽然你做实验很难做出来,但是从理论上来讲,这个this只构建了一半,你就把它拿出去用了这个叫this溢出问题。来这个问题听懂的,给老师扣个一。这个面耳题相对简单。

但是美团的这道题呢实际上是相对非常复杂的一道一道题。我们翻回头来再来看美团这道题。委团人道题呢,他是这么来问的,他说DCL要不要加volat?呃,我我先问大家,DCL用我解释吗?估计得解释。

DCL要不要加朋友?DCLDCL是一种编程模型,用的特别特别多。需要解释的给老师扣2,不需要解释的扣1。嗯。看这里。看这里啊。嗯。我们来解释DCL。就得打开我。讲的另外一门课叫设计模式。

Design patterns。嗯,设计模式。啊,我们来看那个设计模式这门课里面我讲的一个单立模式。呃,首先解释什么叫单利,这个我就不不问了啊,因为有同学真不明白什么叫单利。

我简最快速的解释单利呢就是保障某一个类的对象只能扭出一个来。最简单的实现方式是这种。比如说我们有一个对象。magger01,然后呢,我我只能允许你有managger01的一个对象,不允许有多个对象。

那我可以上来二话不说,我先把自己的一个对象给扭出来m01 instancet等于new manager01。同时把构造方法设成private,别人永远谁也拗不了,只有我自己能拗。那当然了。

我这扭出来个对象之后,别人怎么用啊,我提供一个方法,这个方法叫get instance。然后呢,return。你在后面用的时候,不管你调用了多少次这个方法,你拿到的永远是同一个对象。

来这小程序简单读一下,读明白这个程序的基础之上,我们继续往下探讨这个东西呢叫做单立模式。这种实践的方式叫做扼汉式的单力上来二话不说,非常饿,二话不说,先把它扭了再说。这是你的老婆,你的老公。

husband,你的husband从法律上来讲,即即便你有一个class叫husband,但是法律上来讲,你只能有一个husband,有且只有一个。不然你就犯罪了,你重婚罪。

但是呢如果呃如果这个class叫做boyfriend,就是你的男朋友,那你理论上你可以有多个。虽然说法这是法律上起码不会治你罪,只是道德上你会遭遭受到谴责而已。所以有的时候我们是需要单立模式。

就是你从语法上来直接给他规定好,就是他就只有这一个only one。就这意思。好啦。呃,当你呃理解了这件事之后呢,这个单例模式比较简单。但是呢这个单利模式的写法呢会稍微有一些麻烦的地。有有人挑毛病。

毛病在于哪呢?同学们你们想想。我有没有husband,有没有 wifeF,二话不说,先扭一个出来。对吧我我我我先先先先遛一个出来,但是我还没用上呢,我还用不着husband,我还用不着wi。

你给我拗出来,不是占空间,占地,我还得养着他,还得给他吃饭,累不累?我能不能什么时候我想用的时候,我直接调get instance的时候就表示我想用了,我想使用这个对象了,你再给我拗出来啊。

这个简单对不对?这个写法特别简单,就是我们在get instance方法里面判断一下嘛。如果instance空,然后给你扭出来。那是那意思就是说如果你不为空,说明已经拗过一遍了,就不要再拗第二遍。

直接return就可以了。这种呢叫做懒汉式。嗯。嗯。当你听明白这件事之后。懒汉士也有他的问题,问题在哪呢?在于多县城访问的时候,你很可能拿到的不是同一份husband,什么意思?同学们,你们仔细想一下。

现在有100个县城。我们同时调用get instance。输出他的 hasash code它会是一样的吗?不会好下看就知道了。游戏中间我sleep了呃一个毫秒,让他让这个程序呢把这个问题暴露的更加。

快啊,看这里。你看啊那这个还是扣的明显好多个嘛,对不对?好多个完全不一样的。所以呢呃在多线程访问的情况下,你这种写法是有问题的。来这块能ge到的给老师扣个一。保证不了单利。对,没错。好。

当你保证不了能力之后啊。你该怎么做?解决方案应该是非常的简单。上锁不就完了吗?直接二话不说。在这个方法之上,上把锁 synchronize。这太简单了是吧?啊,上把所你放心,上班所就代表的什么?

上把所代表的是只有我一个县程执行完整的代码的时候,另外一个县程才可以开始这段代码,你知道吗?就是原来的那种并发已经变成了序列化了。所以你想想看啊,你第一个线程执行完了,同步好了。无论如何。

第二个线程再来访问的时候,这个instance一定不会空。所以呢他拿到的永远是你6好的那个对象,只要有你你有一个就可以了。当然,这是上诉,我就我就不给大家看结论了,这个肯定没问题。好,当你上完锁之后。

带来的问题马上又出现了,这个问题是什么呢?这问题在于,假如说你这个代码里面有一些业务逻辑。那么这些业务逻辑跟你这把锁实际上关系不大。啊,从数据库里读一些数据展现出来,你说跟上班跟这把所有关系有多大呢?

不大。但是如果你的这把锁锁定的范围,包括了这些业务逻辑的话。实际上叫做包含了一些不必要的业务逻辑。你的锁的力度或者锁的范围过宽了。这个一般我们认为critical section叫做过宽了啊。

叫做临界区过宽。好,这个临接过宽了,就代表你效率肯定低嘛,对不对?你执行一段代码,你你上锁的代码,你肯定是执行的越快越好,你加了很多不一要的逻辑,太浪费了。那这时候怎么办?怎么办呀?同学们。

简单把锁的力度变细就可以了,怎么怎么变细?怎么做?很简单吗,把业务代码放过去,根本我就不锁你了啊,你这个互相之间同时访问没有问题,只读。好,只是在这加锁就可以了。上来判断if instance等空。哎。

如果你为空上诉。上管所有对象出来。那么如果不为空。直接拿来用啊,很简单。来这会儿能跟上的给老师扣以,我讲的速度还算是挺快的。😊,嗯嗯, good不错。应该样说明你们这个记录还可以啊,凑合。嗯。

我我我们继续聊,我想问大家一个问题。这段代码有没有毛病?呃,能不能够保证?最后的数据一致性可以吗?来看结论啊一下。在这里,我们最后看看他最后输出的结果是有多少个对象,你会看到啊。

你会很明显的看到拿到的绝不只是同一个对象啊,中间有32结尾的,也有264结尾的。为什么会这样呢?我上了锁为什么不行呢?其实很简单,问题出在这,我们简单思考一下。

第一个县程过来的时候判断instance等空等空吗?等空没问题,一个县城先暂停。第二项程过来的时候判断insence等空等空吗?等空。好,第二项程开始上锁。锁定。没问题,我也没人跟他抢。

锁定完了之后扭对象。好有这个对象已经扭出来了,成功。然后是锁匙放把锁匙放掉。好,到这个时候,第一个县程继续运行。注意第一个线程已经判断完了。第一个县程申请上锁能锁定吗?可以。

为什么第二个县程已经把锁释放了?锁定。又扭了第二个队象。所以已经扭出来两个了。因此,你拿到的未必就是同一个。这个问题主要出在哪呢?主要出在。这里。好了呃,终于诞生了这种写法。

这种写法就是著名的DCL的写法。我们来看这个D四条的写法和上一段代码区别在哪?很简单。当我们一个现场判断完它等空之后。上锁上完锁之后,再判断一遍是不是依然为空。你交了你女朋友了啊,你判断了。

你确认了她没有和前男友藕断丝连。好在你。结婚的时候再判断一遍有没有藕断丝连。然后再决定领结婚证,就这个意思。好了。呃,上完锁之后再判断一遍,避免有有其他的线城已经在这个时间段之内上完锁已经把它扭出来。

OK这个东西的全称呢叫做double check lock doubleouble check双重检查锁,为什么叫双重检查?这里检查了一遍是不等空,这里检查了一遍是不等空,中间加了一把锁。

所以叫双重检查锁,叫double check lock。OK这就是DCL的由来。啊,这代码理解一下。

我们把流量代码了啊。

复制一下。方便手机档我稍微放大理解形式的代码,这段代码就是著名的double check log,很多的开源软件都用它。嗯,很多开源开源软件都用的啊,所以呢。嗯。呃,这个这个以后提DCL。

你就直接脑子里浮现双重检查就可以了嗯。好,当你明白了这件事之后。我们来看那个。下面的这个这个这个程序。嗯。我相信呢关于双重检查呢。呃,这个同学们会有一些小小的疑问啊。为什么可能会说会这么说。

这个以前有同学提过说老师啊,这玩意儿有什么用啊,你直接把它删了不就完了吗?我也面这层检查有屁用屁用没有一上来2号不说上锁,然后再判断它是不等空,不就OK了吗?搞定。😡,干嘛要外面再判断一下。需不需要?

来思考一下。给大家10秒钟时间,你好好思考。如果我们把外面这行给删掉之后。会产生什么样的不利的影响,有没有?一定有。为什么同学们,你们琢磨一下。😡,如果说啊你是我们假设说1万个线程。

现在1万个线程来访问这段代码。那。第一个县程已经上完锁了。然后第二个线程上完锁,第一个线程上完锁扭出对象来了。第二个线程再来访问这个对象的时候,他就已经不为空了。如果说外面这段代码没有这1万个县城。

所有的县城,1万个县城,所有县城都得上一遍锁。才能拿到这个对象来用。但是。如果外面这个检查有,你会发现,只要有一个线程已经把它给扭出来了。那么其他县程只需要做一个简单的判断。

这个简单判断呢大概是需要几个纳秒的时间就可以。但是你上锁的话,这个消耗的资源就太大。所以你发现如果有外面这个写法。外面这层检查。1万个县城里只要有一个县城上一把锁就可以。如果没有外面的风检查。

1万个县城,所有县城上一万变所。效率不就变低了吗?这块能听懂,对不对?嗯,这个问题比较容易解决。好,我们说最难的问题难的问题在于这段代码有没有什么毛病?有没有什么毛病?好,毛病在这儿仔细听,认真听。

我呢还是得把这代码复制过来。然后。你看这里。嗯。呃,再稍微复习一下啊,对象过程分三步构成。没有对象。是。默认值,然后调拨的方法是初始值啊,然后建立关联。哦,陈德林。来开了小程序。再看这段代码。

在这段代码开始执行的情况下,假如我们现在有两个县场。第一个县城。判断为空没问题,上锁没问题,判断依然为空,没问题。接下来有对象。接下来我们假设第一个县程已经执行到哪步了呢?已经执行到这步了。

第这是第一个县程执行的步骤已经执行到这儿了。回想一下啊,我们你有一个对象的时候是三步构成,还记得吧?这三步分别是new invo special和a store。好,接下来。接下来第一个选中来了。

thread一执行到这句话了,执行到这句话之后,扭对象扭了一半,刚刚扭了一半。6T这里的M值为0,本来它正常值为8。然后呢,调购的方法建立关联,结果正在这个时候发生了指令重来序。刚才我说过。

两条指令之间是可以互相换顺序的。哪两条指令换了顺序呢?四和7这两条指令划了顺序。另重牌。好,再看一遍,第一县城过来的时候,扭到了一半。发生了指令重排序。发生指令出歪序会把S store调到前面了。

S store调到前面是什么意思?T直接指向这个初始化了一半的对象。来这会能跟上的给老师扣1。啊,那么大家你想一下。地址箱的一半的对象。指向了一半的对象。好,正好在这个时候第二个现场。

第二线程也是执行这段代码,他上来之后先判断它是不是等空。哎,你告诉我。你看这个内存的图,它现在等空吗?等不等空替等空吗?不等空不等空的话,后面还执行吗?不执行,是不是拿到这个T就直接拿来用了?

你的男朋友刚穿了一半衣服就出来见人了。不好意思,这个值只拿到了M等于0。你本来正常是应该M等于8的。如果这记录的是一个很简单的一个呃。比如说是那个双十一的期间,这里记录的100万单。

然后突然之间呢不一访问有一个显程访问到的是零完蛋。嗯。来再来看一遍。这一个。第一个县城。六对象啊,判断为空上锁依然为空,所以开始拗扭了一半,发生指令重排。结果这个T指向了一个半初始化。第二个线程来了。

先判断嘛,判断它是不等功,一判断不等于空了,直接拿来用,结果第二个线程就用到了初始化了一半的对象。好了。所以这个线程是有问题的。来,大家听明白这件事的同学给老师扣1。但这个bug非常的隐蔽。

有同学可能会说了,老师你讲的这事儿不对呀。你schronize的什么概念?schronized的可是做了内存同步的。😡,我的天,你做内存同步,你居然说能让我看到了遛了一半的对象,你不扯淡吗?😡。

有没有同学有这个有这个疑问?synchronize本质上是一个什么概念啊?它比较复杂。其实本质它的执行比较复杂,就是schronized做完的一个东西呢,必须得是内存的。最后最终同步完了之后。

另外一个线程才能看。我再说一遍。哎,对打开我们的那个刚才那个代码。我再说一遍singronize什么?synchronize的概念就是说我下面必须都得执行完了,我把里边的内存呢做好同步了。

我这内存状态改完了,我才会释放所其他的线程才能访问到里边的内容。我已经拗完了,你怎么能访问到我中间状态,你不扯淡吗?能听懂我的我的问题吗?来,这会儿能听明白的,给老师扣个一,就是问题在这。

现在的问题就在于第一。synchronized的执行的现程内部能不能重排序?第二。synchronize的中间状态会不会被别的变现成独道?好,听我说,我们先回答第一个问题。

schronized执行到内部的时候,他内部的指令能不能重排序,这件事超级简单。我刚才讲了。能不能重排,取决于你是不是能保障最终一致性?如果能保障最终一致性,随便你排。同学们,你们琢磨。

我这个先建立关联,还是说先给他初始化,最终的结果是不是一样的呀?所以中间的这几条指令,您老人家随便换,没事。所以。schronize的内部重排序是没问题的,认真听好吧,这里头很多那个。

别的说说法都是有问都都不对啊,完全能重排。第二个schronnet内部的中间状态会不会被别的线程读到?为么?如果另外的线程执行的是同一段schronnet的代码,它一定会读不到,必须得等一个线程执行完。

另外一个线程才能读到。但是很不幸的是,我想问你的是,第一个线程执行到了synchronnet里边代码,第二段线程执行的是哪个代码啊?他是在新空台的内部还是外部?没有锁定的代码能听懂吗?

一个执行的是被锁定的代码,一个执行的是没有锁定的代码。我告诉你,这两个互补冲突,你里边执行的任何状态,外面都能读到。这个东西就是大家伙都是并发执行。好了。

两个问题我就解答完了。

系列 4:P25:【JVM大厂面试真题】学员问题答疑 - 马士兵北京中心 - BV1VP411i7E4

约一内以外的概念。这个东西呢,我我VIP课上给大家做过实验的啊,绝对是能向大家证明这一点。好了。

现在已经是9点44,我说过我9点50会打广告。5分钟。当然还有两大问题啊,就是这两大问题也比较复杂。hosport为什么不使用C加加class到底是对还是方法区?我一会给大家讲这里面尤其是第二个问题。

尤其是第九个问题。呃,最近被问到的,你想答的很全呢,不容易。🤧嗯。

嗯。ok。5分钟我答一下刚才我这个问题的答疑,看看有没有。

明白了明白了是吧嗯。😊,什么病外之音,刚才声音有点小,没听清大哥,你把你的声音放大啊,其他人都能听清,你没听清,把你的那边的声音放大好不好嗯。😊,小月月,笔先对。最大了,因为我这边一放大它会有杂音。

你知道吧?我给你增议一下啊试试。5分钟答疑,刚才我提的我讲的这些有疑问的地方,你随便问你把老师问到了,老师这课就可以送你了。任何问题,关于JVF呢,您老人家随便问。好,讲讲怎么叫?猫了头。

我刚才故意略过这个,结果呢你非得。非得把让老师把这个事给你调出来是吧,听我说要不要加包了条,必须要加。

vololaile什么概念啊?就是你你在。

double check里面。double check里面你要定义这个。呃呃呃,这个这个代理对象的时候,必须要加volleile。为什么要加vol了条?原因是V了条能保障你两方面的作用。

第一个呢叫保持县城之间的可见性。第二个呢,叫禁止指令重排序,能听懂吗?叫禁止重排序。就是您老人家那两条指令,不就是刚才换了顺序的问题吗?产生了问题。没关系啊,我可以给你禁掉,叫禁止重排序。

所以必须要加va。当然。我老怎么是禁止怎么禁止的?😡。

这个东西要讲到内存屏障。今天的时间肯定是讲不完的嗯。

完了在哪看说这里可吧有优化,有什么优化。都有哪些指令,执现在一般什么顺序指令。java大概是200多条。执行的什么顺序,一共有8条规则,叫不可以冒犯这8条规则。只要不犯这8条规则,其他指令随便排序。

这8条规则我就不给你背了,但是这东西你不需要背过,因为它也比较简单。比方说你扭出县城来之后才能执行。像这种规则,类似于这种的,能听懂吗?你放心,这8条规则里面从来没有哪一条规定说我拗了一半的对象。

不能复值。所以刚才我讲的质量重白序是完全没问题。X等一X等2会丢掉第一个吗?什么叫丢掉第一个呀?你说说啊,你X等于一X等2肯定会留掉第一个呀嗯。😊,对,这条规则叫8条happens before原则。

如果有兴趣,可以百度一下。或者找咱们VIP。听老师给你讲。为了给你们讲这个课,我可以这么跟你说。为了给你讲这么这个课嗯。基本上我市面上所有关于JVM的书啊。

以及包括JVM虚拟机规范这种这种基本上那个不是写JVM的人都不读的人,全部跟你讲,全全部读完。

所以关于这VM您老人家随便了,我给你讲的这MM课呢叫做总结了十几本书,外加上各种问题,外加上这M虚拟机规范给你总结出来的嗯。这地可以不针对这外面体系优化,那多了太多了,这没法说了,就优化太多。😊。

因为你们这个优化什么叫JVM优化呀?😡,你看你这问的这个问题吧,你说的那个为了中国人民呃过上那个美好的日子,这个我我我我们党我们国家做了哪些优化,你说这玩意儿怎么跟你说?😊,听我说有哪些优化。

有些优化是需要你自己做的元旦老人。什么叫做JVM调优,能不能理解?JVM调优这件事就是JVM里面。有好多参数你需要进行调整,调整到你GVM的自由状态。JVM的条有呃这个参数有700。多个参数。

GVM参数本身有700多个常见的调优的大概是有五六十个左右,50到60个。需要你进行组合使用才能调优。我要给你讲这玩意儿,你说我能给你讲完吗?起码今天讲完。面试的时候经程这么那些优化调整。你问他具体的。

你说哪方面的?你比如说执行层面的,他有那种JIT。是吧。就是那个及及及及时编译,他有呃这种C one级别的优化和C two级别的优化。D个128版本木封。你问的这个问题是。嗯。

那个谁的第九题,美团的这个第九题哦,还不太一样,但是也差差不了太多。你问的这个问题,基本上是每年的第九题,就是class项是对岸的方法区,实际上本质上跟你这有点类似啊。最终一致性判定比较复杂。

对他变异器的优化。这是在。

系列 4:P26:【JVM大厂面试真题】为什么hotspot不使用C++对象来代表java对象? - 马士兵北京中心 - BV1VP411i7E4

我们聊完最后遗留的两个问题啊,看这里。呃,这么跟大家说呃,第八个问题和第九个问题呢会相对复杂。这块呢你仔细听,认真听,能听懂就听,听不懂呢,你就直接我帮你打开一个思路就可以了。看这个思路叫做。

为什么不使用C加加对象直接表示ja对象?我直接告诉他要答案。这个答案是这样的。C加加对象和java对象的主要区别。这块由于很多人没接触过C加加,我直接说结论能听懂就听,听不懂就算。

是因为C加加对象里自带了一个叫做 virtualrtualtable的东西。这个东西呢叫虚函数表。来学过C加加的人,能不能告诉我这东西是什么东西啊?这东西是实现C加加多肽的关键。

本质上java实现也是通过这玩意儿来实现的。只不过java里面把这个虚函数表挪到了class文件里面。好,有没有理解这个虚函数表的,有的话给老师扣个一。有吗?哼。了解虚函数表的。嗯,锐瑞瑞嗯不懂是吧?

不懂就算了啊。总之可以这么说,C加加的对象里面比java对象多了一个东西。所以如果还采用这种来呃做这件事儿的话,那么Java对象里面的它的。它的大小会膨胀的比较大,java追求的叫做紧凑。紧凑你懂吗?

就是它编译出来的class文件,它会非常的紧凑。😊,会追求字节呢相对的比较小。因为原来Java的设计是在网络上进行传输,那会儿的带宽没有显得这么宽。所以在C加加里面,在Java里面设计了两种两种东西。

把这个虚函数表从对象里头挪走,虚传表挪哪去了,挪到了class文件里面。所以叫做OOP class2元模型。好,不懂就算了啊,这个问题相对复杂一些,难一些。

系列 4:P27:【JVM大厂面试真题】Class实例究竞在Method Area还是在Heap? - 马士兵北京中心 - BV1VP411i7E4

你看。这个问题就是第九个问题,叫class的这个实力究竟是在mesage area,还是在hiap里面?对,只要的实力方法都是序方法。没错,所以它的class里面全是序方法。啊,这个问题这个问题。

如果说呃一个中小厂在问你的时候,你就直接class文件,肯定是在me area了。这个不用说了,肯定是在这儿的。但是我告诉你,在一个hospot的实现里面,比方说我们扭了一个大O对象。

这个对象本身是在classus是在堆里面。这个对象指向的class文件。它会位于我们的方法区这个方法就叫med area。但是注意的是,这里的引用指向的是一个C加加里面的一个对象。

在这个对象里面又有一个引用,这个引用指向的是堆里面的关于O点 class。所以严格来讲,O点 class是位于堆里面,为什么放堆里方便反射调用?方面反射。所一上来讲,class的文件的信息有两部分构成。

第一部分是C加加的内容,这是关于这个class的一些原原数据的信息。第二部分呢是关于呃可以用来做反射的ode class的内容这部分内容放在堆里这部分内容。放在me area里面。合同吗。来。

这块能听懂的,能get到的给老师扣个一。Yeah。已经报名了,我升职加薪之后靠你了老师,你来就是了。老师要让你升不了职,加不了薪,你任何人都都不可能让你做到这一点了就。😡,嗯。好了。呃。

当然这里面还有一个没get,哪儿没ge,你得提问出来,我这几个名词你哪儿没明白,什么地方没明白。比方说我们常见的这种JVM的内存溢出。GVM内存一出叫做out of memory。好。

这些对外M内存溢出,实际上这里面的对象变多了,内存里面装不下了。还有一种内存溢出比较特殊。这种内存溢出呢叫做。matetter space的溢橱有没有听说过?

permanent generation永久区的溢出。好,这两种东西。Mes area。还是有JVM嘛,你随便问问导老师算你厉害啊。Okay。

系列 4:P28:【多线程与高并发】课程规划 - 马士兵北京中心 - BV1VP411i7E4

He。好,同学们,我们开始上多线程和高并发的第一节课。我首先跟大家交代一下咱的这个版本里头,我给大家讲哪些方面的内容。呃。那么老师呢会给大家讲多线程和高并发啊,这两大块应该说。怎么说呢?就这两大块啊。

是现在面试里头问的越来越多啊,也是你从一个一个相对初级的成序员,然后向比较高级中高级的这方向的迈进的一个必须要踏过的一道坎。呃,我先跟大家简单交代一下,就是后面会讲的哪些方面的内容。无论如何呢。

这些方面内容呢都会给大家讲完。呃,我的预测是4到6个周末啊,这个不一定能够讲完。如果讲不完的话呢,呃咱们再往后就拖一拖。另外呢呃老师讲完这块之后呢,会讲那个JVM呃,原来排的操作系统的课呢。

排的JVM后面会比较合适一些。呃,我后来考虑了一下,因为先讲操作系统其实呢那里面呢也有很多同步的东西。那么同步的这块呢,实际上和多性程和高定方案啊。有些冲突,我们不如先学最直接的。学完这个之后呢。

我们先学在学JVMJVM也是离我们最近的。呃,你要是想去跳槽的时候,马上能用得上的。呃,在这个之后呢,我们再来讲操作系统,其实你理解起来呢会更加相对容易一些。呃,我大概讲六大块,呃第一大块呢基础的概念。

什么是现程开始啊,今天我们基本上就能把基础的概念应该讲差不多。那么第2块呢是JUC的同步工具。第3块呢是同步的容器。第4块线程池。呃,第5块呢是高频的一些面试的东西啊。

呃,包括县城,第6块呢是呃destructure。呃,不知道有多少同学听说过这个框架的这个框架呢,它也是1个MQ框架。

呃,把我的画图软件调出来。这这个。对。嗯嗯。我先他0。Yes。

Yeah。那么这个框架呢也是一个MQ的框架啊。啊。一く。好,这MQ叫什么呢?叫message。Q。叫消息队列是吧?那消息队列呢非常多啊,后面还会有老师给大家讲那个呃actMQ啊,卡夫卡呀。

这些都是消息队列啊,包括radis也可以作为消息队列。好,我给大家讲的这个,如果你能在简历里都体现出来,并且能够跟面试官说清楚,这是1%万%的加分项目。呃,这个呢是叫做destruct。

应该来说是目前大家伙公认的,在单机环境上啊,效率最高的性能最快的这样1个MQ。讲到的时候我们再聊这个问题啊,得需要了解前面的关于病发的这部分的内容。

系列 4:P29:【多线程与高并发】线程的概念 - 马士兵北京中心 - BV1VP411i7E4

你脚多线能高病发啊。内容上我就唯一重复了,刚才跟大家说过了。嗯。😊,呃,我先说一下为什么要讲这个多线流和高并发呃,原因是什么呢?原因是现在啊呃如果你想拿到一个比较高的薪水。

在面试的时候呈现了两个方向的现象啊。第一个呢叫上天,第二个呢是入地。那么入地的这部分呢相当于就是那个很多特别基础的内容就越问越基础。上天这部分呢高并发缓存大流量。是这部分的内容。今天我要讲的现场呢。

实际上是入地这部分内容啊,土行孙这部分的内容。我们那先讲,第一个就是我们先从那个什么是县城开始给大家复习,这个是给大家稍微复习一下啊。呃,不知道有多少同学是嗯基础不太好,说什么是现程都不知道的。

不知道有没有。如果确实有的话,听我说这么内容我花的时间肯定不会太长。呃,老师的那门基础的课啊就是。特别特别呃老的那个视频里头那个讲的基础的课程。如果你现成的概念不清楚的。

先去那个课里头找到现成那一章是第十1章。先把那部分内容看完,看完,你才能听得懂后面的课。找,不知道说清楚没有啊,同学们。那个王明天涯说老视频不是很清晰,这个没办法,他是好多年前录制的。呃。

那会儿那个屏幕最大的分辨率还抵不上现在的4分之1呢。所以这个是没有没有办法的事情啊。不过在代码应该是大致能看清楚的,我看过嗯。那么今天呢我先从到底什么样是一个。现程啊来开始给大家复习。什么是县程?

有这么几个概念啊,第一个呢是什么是进程?什么是程序?什么是进程?什么是县程?什么是县程是吧?这几个概念呢。

嗯。

想想啊,我是在哪块儿给大家讲的这。嗯。Yeah。有这么几个基本的概念啊。第一个呢,什么是呃一个进程,什么是一个县城,什么是一个携程,或者叫什么是一个县程。那,这个我们后面还会讲,这个不多说。呃。

什么叫一个进程?什么叫一个现程?做一个简单的解释,你的硬盘上有一个程序。这个程序是什么呢?叫QQ点EXE这是一个程序,好吧,叫它program。好,这个程序是一个静态的概念,就是它扔在硬盘上,没事。

是也没人理它。但是当你双击它哎,嘣儿,它就弹出一界面来。然后你输入你的号码密码,你就进去了。OK这个时候呢叫做一个进程,就是它起来之后,一个程序运行起来之后叫一个进程。所进程呢相当相对于程序来说。

它是个动态的概念。这个意思。呃,作为一个进程里边最小的一个执行单元。其实呢它就叫一个现成这块呢。估计有的同学如果基础差,可能听不太明白。我在这儿呢给大家做一个小小的演示,看这里啊。

怎么样子才能起一个现程。现成启动的方式呢,我一会儿再讲啊,我们现在呢。先定义一下呢,到底什么是现成。呃,定义了一个class,这class呢从哪个类继成呢?从thread这个类继承。好。

重写它的run方法已经重写完了。在这里面我要想调这个run方法,有两种方式认真看。那么第一种呢是new three new T一点run,我就直接掉了。在闷方法里面,我掉的妞体一点run。

在这里面呢它会输出T一。然后。在我的ma方法里调完了T一的入方法之后呢,又会不断的输出T2。sorry不是T2,而是ma。运行一下。Okay。跑一下看看啊。嗯。好,结果你会看到是吧?

T一先输出T一后输出妹。好,这种方式叫做方法调用。你直接用了个提议这个对象,然后调了它的re方法,先执行re方法完了之后马上执行后面的输出 main的内容。但是呢你想运行这个run。

还有一种方式就是new T一点star。为什么它用start的方法?是因为thread这个类里面有start的方法。连体一star,然后与此同时,ma方法开始运行。输出的结果。你们看到呢和原来大不一样。

是ma和T一交替输出。原因是什么呢?当你调t的方法的时候,从这个地方会产生一个分支,这个分支会和我的主程序一块运行。如果用图来表示的话。润方法的调用相当于呢。ma方法开始,然后b跑到run方法那执行。

执行完了之后再回来继续ma方法执行。所以它先输出T一,然后再输出main说来说去在你的程序里头呢,只有一条执行路径。但是如果当我们调star的时候,好,到这儿了,到start这了。ma方法继续运行。

与此同时。run方法同时运行。OK这个呢就叫做不同的线程,同时运行。好了,所以现成的概念用一个最简单的啊,不用那个书上书本上那些刻板的那那那些数语来定义的话,非常简单。一个程序里不同的执行路径。

就叫做一个现程。

系列 4:P3:【JVM调优实战】对比:Golang与Java的GC - 马士兵北京中心 - BV1VP411i7E4

用pyython语言,用java语言,用go语言写一程序。仨月写完了,你拿CC加加写,你写一年。等你推出来的时候,市场都没了,黄花菜都凉了,有用吗?没用,所以后来产生了很多很多的对内存管理比较友好的。

知道吧?方便内存管理的。语言。他方便方便在什么地方呢?大家注意他方便呢并不是方便在说。那个多线程的情况下啊,没有不会产生什么不一致了,没有也子针啊,不是这么回事。它呢主要方面在引入了DC这个概念。

这里的DC呢指的是gaby值。Collectctor。gabbby这le的意思是说哎呀,我这哪有错吗?隔喱处。好,Gby letter。garbage collection叫垃圾收集器。

垃圾收集器是什么概念呢?我给大家举一个形象点的例子,就是我们平时写写一些小程序啊。😊,就是在这块内存空间里面不断的分配对象,分配对象,然后删除掉删除掉啊,再继续分配。

再删除这个对象呢有可能指向另外一个对象,这个对象的成员变量有可能指向另外一个对象。好。在内存空间里面不断的扔这种小线团,这小线团之间呢建立各种各样的关联。也许呢它上下面有好多好多的成像变量。

建立建立好多好多的关联等等,会形成一棵对象树。这个对象树呢在不断的动态的产生变化。如果站在内存角度来看这幅图的话,就这个图景就是这样子的。原来我们必须得小心翼翼的管理,说这块没用了。

我就得小心翼翼的把它删掉,不能多删,不能不删。但是像这些语言,java语言、pyython语言、狗语言,以及原原来老早的这个list语言啊等等。它呢引入了一种GC的概念。GC的概念就是说。

我自己这个程序,我的业务程序,我自己不去维护删除这个过程了,我只管分配。只管分配,那么就有必须得有人负责帮你删除,不然你的内存不就很容易就被占满了吗?好,我引入另外的一个另外的线程,另外的功能好。

这个功能叫做GC叫做ga letter叫垃圾回收器。javapyythongo都有这个这个功能,它的程序一起来之后,它并不是说只启动你的业务线程,它会同时启动好多线程。这里面的线程就包括垃圾回收现程。

OK这个垃圾回收器的功能是什么?就是你不用你再也不用管。这个你你你只管分配内存啊。应用写程只管分配。好。垃圾回收器负责回收。当然,这是一个很复杂的过程,因为垃圾回收器负责回收,那些线头不是你自己分配的。

你怎么知道它什么时候就不用了呢?😊,所以你首先你得首先找出来谁是垃圾,然后再采用各种各样的方式去回收它。我这么讲,不知道大家能不能理解,能跟上哪老师扣个一。然后像这些程序写起来就比较简单。

你就不用去管这些特别难以调试的bug。这些呢特别难以调试bug呢相对难难以产生。当然。多线程的麻烦就在于,不是说呃你这个指针被别人删掉了,这只是其中一种bug。多线程还在于说我们去共同访问的时候。

数据的不一致性。这个了解过多线轴呢,应该我一说你就明白啊。好。并不是说他会把所有的这些问题全部给解决了,不是这么回事。呃,因此呢这些语言一旦诞生之后就开始流行。为什么?因为它开发效率非常高?

大大的降低了程序员的门槛。ja油语言诞生之后呢,很快就流行。呃,原来学CA的学CI加的很多都是转向java了,为什么?因为它简单。在这个方面,起码在这个方面比C和C加加简单的多。好你。

这是这些语言的诞生。当然呃每一种语言呢都有它自己的垃圾回收的内容啊,都都不太一样。我呢在我们的VIP课里呢讲过java是怎么样垃圾回收的,讲过go是怎么垃圾回收的。python相对简单。

python就是使用的这种这种叫叫引用技数啊,它它的算法相对简单。嗯,但是讲到这儿呢,我也得朝我们我我们讲我们是讲到了现在啊,从过去讲到了现在,现在呢这些语言很流行。但是呢这些语言有很大的问题。

他也没有解决。什么样的问题呢?就java个控指针的问题依然没有解决。你能保证你传给java的任何一个引用,它不是。控制针吗?很难保证你有一参数,你接触过来之后。

你是不是在java程序里面还得跟那判断判断啥if你传给我的参数不等于空。怎么怎么办?就说这个你依然不能保证它是不是控制帧。虽然java呢呃有各种各样的什么option啊。😊。

什么什么呃对于空指针的这方面管理的类啊,但是他依然没有解决这个问题。就是野指针的问题依然会存在。也指针问题在java里面依然会存在。OK。好。python里面go里面,我告诉你依然会存在,这是第一个。

第二个呢,同学们,你们拿大腿想想看,作为我来说,我只管分配。😊,有另外一个人来帮我回收。那么他回收的时候一定会占用。CPU的执行时间一定会占用CPUCPU资源,一定会的。所以它的执行效率相对低。

所以我们说java写的程序,python写的程序,勾元写的程序。相对于CC加加来说,你放心,没有人能超过他。他们的效率在长时间运行的时候一定会低。当然,这些语言都自己都自己都会吹牛逼啊。

说我Java采用了GIT是吧?justin timecompr啊叫即时编译器。采用了之后呢,我跟C和C加加差不多,你废话,你采用了之后就就是那么一小段程序和C加差不多好吗?

并不是说在比方说我我7乘244小时365天不间断运行的这种服务器程序上,你总体算下来一年算下来和C和C加加的执行效率差不多,不可能。😊,好,第21个呢,pyython那就更不提更甭提了。

勾语言呢号称啊我是替代C的,所以我的执行效率特别高。OB我比java还高扯淡。够也有严重的这种垃圾回收器占用的时候,停顿时间叫STW就是我垃圾收垃圾收集器开始干活的时候,你其他的线程都得给我停住。

生产环境之中,有人遇到过的够语言的垃圾回收。停顿时间长达数个小时,所以大家千万不要迷信一种语言。我呢讲东西呢,我是喜欢站在架构师的角度讲,我并不偏向某一种语言。但是我需要用某一种语言来落地。

最流行的是java。现在呢呃有一些地方在开始认购,所以呢我又讲java要讲购。其实呃站在一个牛逼架构师的角度来说,语言呢只是一个工具而已。作为一个结构结构化设计师啊架构是吧?你要盖一座大楼的时候啊。

这个柱子该用水泥,用水泥,这个门该用木头,用木头。然后这个洗手台子该用塑料,用塑料啊,该用化工的,其他化工材料,用化工材料。呃,如果从软件角角度讲呢,你做你造一个非常非常复杂的软件。

你这个地方该用C加加用C加加该用python用pyPthon,该用go用go,该用ra用ra。所以我希望大家呢在以后你的学习和成长过历程里头超越语言,站样在一个更高的角度来考虑问题,建立架构师的思维。

你的薪水才能够做更高的突破。可以这么说啊,任何一种语言包括这样吧,包括pyython,你如果只是局限于这些语言的时候,告诉你你的薪水,一线城市目前差不多三五十万到头了,超过这个数的很少。

但是如果站样在一个架构师的角度,他的薪水会达到多少?120万以上。ok。来认可老师这句话的老师扣个一。Yeah。java还没学明白,没关系啊,语言这东西呢你就理解为它是一把大砍刀。😊。

你学会用斧子砍柴了,下一步你就是用菜刀切肉。如果用菜刀切肉,你学会了,下一步你是用水果刀削水果,你说它很难吗?不难很类似,需要你就是就是熟练度不同而已,好吧。所以这两类语言叫做有什么特点呢?

这类特点就是它的执行效率非常高,但是它写容易特别容易产生bug,你得手工去管理自己的内存。好,这是这类语言。这类语言是什么?这类语言是它开发效率特别高。但是你管理呃内存的时候。

你你你你你你呢它执行效率就会比较低。这个内存的管理上呢,它就会引用另外一个让别人去管,我我自己不用管,我省了很多事儿。😊。

系列 4:P30:【多线程与高并发】线程的启动方式 - 马士兵北京中心 - BV1VP411i7E4

很多时候呢我们呃作为真正使用这些概念的人啊,不需要把概念说用特别文绉绉的方式表述表述出来。因为编程呢是一个工程学科,你能理解能用通俗的语言表示出来就很不错就可以了。

啊,这是现成的一个基本的概念。我们来看这个县城的怎么样来创建一个县城,怎么样来运行一个县城。创建一个县城的两种方式啊。这个我在原来老的课程里头也讲过,在这呢也是带大家复习。创建现成的两种方式啊。

第一种呢是从thread类继承。class my thread extends thread从th类集成。第二种呢是。你资料集成之后重写re案方法。好,第二种呢是。你定义一个类去实现reable接口。

依然重写run方法。但是如果你用第二种想让这个线程运行起来的时候,必须new thread,然后呢把我的实现reable接口的这个类的对象传进来,然后再调用start。如果你是从th类继承的。

那么你直接调用start就可以。需要注意的是一定是调用start,而不是调用run。

那还有第三种,其实第三种呢也是第二种的一种变形。JDK8之后呢,有一个lamb的表达式。

第三种就是使用lambda表达式的方式,newstr括号啊箭头,然后呃里边怎么写是吧?Systematic, printline, hello lambmbda。给大家20秒钟时间。

看着小程序能不能看懂,有没有什么地方有疑问的。因为我默认的你是了解过现成这概念的哈。好,那么在这儿呢,我突然想起到面试题了,我突然想起来了啊。呃,有的我记得有一个。同学出去面试的时候被问到我说呃,请你。

告诉我。启动现成的三种方式。而且你告诉我几种现能的三种方式。呃,需要大家注意的是呢,这三种方式并不是这三种,而是说第一种是从。thight继承。第二种实现reundable接口。好,第三种是什么呢?

第三种呢是通过现程池来启动啊。一呃 exit。呃,exe。Executors。通过这个new catch的。thhread嗯。you catch the thread啊。然后拿到一个线程值之后。

然后再去通过线程池来启动一个线程。这是他想要的第三种。但其实啊在这个现成池里头起现成的时候,也是用的这两种之一。呃,因此呢他说用三种方式来启动,有点儿有点吹毛求疵的意思。所以你值得理解这个意思就行了。

如果有人问你这方面的东西,你说你说第一个thread,第二个readable,这肯定没问题。好,那第三个呢,你要说leer表达式,如果他不满意,不满意,你就告诉他啊。

线程池通过线程池里头也可以起一个新的线程。

系列 4:P31:【多线程与高并发】线程的3个方法 - 马士兵北京中心 - BV1VP411i7E4

可以起一个新的建程。

OK这是现成的最基本的概念。好。Yeah。呃。

我们来认识几个现成的最基本的方法。那么第一个方法呢叫sep。sleep就是睡眠,所以睡眠的意思,当前现程暂停一段时间让给别的县城去运行。啊,是这个意思。好,那既然讲到这儿的话。

这个睡眠让给别的县城到底是什么概念?如果从操系统的角度来讲的话,这是我们的CPU。CPU啊是一个特别土的特别土的这么一个元件。这个原件呢在它的概念里头是没有现成这概念的。他只知道干嘛呢?

就是他就是不断的一个死循环。这个循环啊就是从那个。内存里头把指令拿过来运行,拿下一条指令运行,再拿下一条指令运行,一直就这么不停的循环,不停的循环,不停的循环,没有指令了,歇着就这意思。

所以就实对CPU来说,没有现成这个概念。呃,但是我们这多线程的是什么意思呢?其实呢是有好多不同的线程。每个人在如果只有1个CPU的话,那么每个人呢就在这CPU上执行一会儿。每个人在CPU上执行一会儿。

直接一会之后,都是你把你扔出去,把第二个线称再拿进来。然后呢,不儿再把第三个线程哎拿进来,把第二个线程扔出去,是这么一个概念。而这个sleve的概念是什么呢?

就是说这个线程麻烦你啊跟我这儿睡500个毫秒。然后在500毫秒之内,你唉别人别的县程可以去运行。

让给别的县城去运行,是这个意思啊,t sleep。那代码我就不跑了,太简单啊。

好,第二个呢叫e业的意思是非常谦让的退出一下。

这个代码呢我就不演示了,你们如果有没有同学对业务的有疑问的,如果有疑问,一会儿一一会儿一会儿找我问啊,我先讲。好,E是什么意思呢?比方说我一个线程在运行,另外一个线程也在运行。

然后当前这个线程在CPU上运行呢,运行到某个程度的时候,它掉了个已有的方法。那业务的方法意思是哎,哥们,我先退出一下,我从CPU上先离开。离开之后呢。别的县城是有机会在这执行的。当然我离开了之后。

如果说别的前程没执行,我还可能继续回来继续执行。所有的离开就是进入到一个等待队列里头。等着干嘛呢?哎,我从本来我正在上面运行呢,结果呢我又的一下右的一下就是哎,不我又回到等待队列里。回到等待队列里。

在操作系统的这个调度算法里头呢,还是依然有可能把你刚回去的这个线程拿回来继续执行。当然,更大的可能性是把原来等待那些拿出一个来执行。所以业务的意思本质上就是我让出一下CPU。

至于后面你们能你们能不能抢到,不好意思,那我不管。嗯。好,这是业的意思嗯。折接据说返回就绪状态,没错,就是返回到就绪状态去。

Yes。

那第三个呢叫join。joman的意思画还是画图啊。如果这是我们第一个县程,这是第二个线程。O。这个重要的意思,如果这线程叫T,如如果这个线程呢叫T1啊,左边这线程叫T1,右边这个线程呢叫T2。

它调的过程呢,如果是在T1的某个点上掉了T2点jo,认真看。在某一个线城里掉你自己的点状元是没有任何意义的。掉了,如果是掉了T2点joinjoin的意思叫加入,那意思就是麻烦你跑到T2去运行。T一干嘛?

T一在这等着,什么时候T2运行完了。继续T一运行。所以join的意思就是哎,当我本来我这线程到这儿了,然后我调了个join,我就跑到另外一个线程去运行。运行完了之后,我第一个来运行。

所以相当于把这个线程给加入到了我当前线程里面。这要你常经常用来干嘛呢?经常用来等待另外一个现程的结束。T1完了之后调T2点joinT2点join的意思就是哎,我等T2结束了,我T1才继续运行。

咱以前有个面试题说,呃,我怎么才能保证另外一个县程运行T一运行这个T1T2T3,我起了三个线场,怎么才能保证这三个线程能够按顺序执行完?这个事太简单了,你运行完运行起来之后。你在那个。

主线程里先调用T一重,再调用T2重,再调T3重。就可以了。还有一种那个更加精确的方式呢,就是你T一里面调T2转,T2里面调T3转啊,保证是T3先完了,T3T2才能完T2完了T1才能完。

啊。

系列 4:P32:【多线程与高并发】线程的状态 - 马士兵北京中心 - BV1VP411i7E4

好,我们讲下一个小节呢,叫做thread the state。は。呃,thread state的意思是threread常见的一些个。状态啊这些状态呢有的是你能够用程序测试到的,有的那是不一定能测试到的。

但实际上确实存在的。

那我这个状态呢我画了一张图。图呢在process里面,我我就不专门打开process on了。这是。java里面的现成的状态的一个迁移图。我们来。呃,大概的。来看了一下啊。

这是我们的线程状态的一个清晰图。这个县城呢目前其实有这么几个状态,一共是几个状态呢?1234566个状态是最常见的啊。呃,听我说。这个状态呢叫new。当我们new一个线程,就是它最新创建出来。

还没有调用start呢。new thread完了之后,哎,这个时候呢它是new状态。当你调用star方法之后,它会被现程调度器来执行,也就是操交给操作镜来执行了。那么操作镜来执行的时候呢。

这个整个的状态叫reable。java里是有这么一个这么一个状态的,叫runnable。所以我才会说这是1234566个绿颜色的点啊,这个大的看代表一个。然后来说是666个状态。

但实际上那个redable呢,实际上它内部有两个状态。第一个呢叫ready,就是就绪状态。第二个叫running,确实在运行的状态。所谓的就绪状态指的是什么?

就绪状态就是说嗯我们扔到CPU的等待队列里面去了。在这个等待队列里面等着他排着队。等着让CPU运行呢。就是这个概念。好,这时叫ready真正的扔到CPU上去运行的时候,这个状态呢叫running啊。

这两个呢都叫做reable。所以。thread yield一旦调用的时候,会从running状态跑到ready状态去OK。现场被调度去选中执行的时候,哎,又从ready状态跑到running状态去。

这个意思。当然你如果顺利的执行完了。好,进入terinated的结束状态。大家需要注意的是,你terinated完了之后,还可不可以再调用sstar。回到new状态,再调用sstar的不行。

这是不被允许的。你完了这事儿就结束了,你想stride结束完了之后,再调用那个str start的方法。sorry没有,不不行,不可能。在reable这个状态里头会有其他的一些状态的变迁。

还有什么状态呢?ch waitinging等着waiting,等着还有block的阻塞。那什么叫什么情况下进入阻塞schronized加上同步代码块。进入到那个代码块里头的时候,没有得到那个锁的时候。

我这个代码写了schronized。但是呢我还没有得到那把锁。阻塞状态获得锁的时候,哎,跑到就绪状态去运行。在运行的时候,如果说调用了weightit,调用了join,调用了park。进入微停状态。

调用了notifynotify all或者unpack又回到runable状态。这个runable状态是ready和running的两个两个状态啊。好。

那time的 waiting呢其实就是说过一段时按照时时长来等待。过这时间呢,自己时间结束自己就回去了,就这意思。是那个。Wait, join。

pack nanos以及pack continue这些都是关于时间的等待的这些方法。ok看看这些关于现成状态里面有没有同学有疑问的点。真的说哪些是操作系统管理的,哪些是JVM管理的。

这些全是JVM管理的。因为JVM要管理这些状态的时候,也要通过操作系统。所以呢你你你你说哪个是通哪个是操作系统,哪个是JVM,他俩分不开。JVM是跑在操作系统上一个普通程序。现成什么时候状态会被挂起。

挂起是不是也是一个状态?嗯,对,这是这个就是没有讲操作系统的一个毛病之所在。但然我讲完这个呢操作系统这个可能这部分你也就听明白了。很简单,就是running的时候,你在1个CPU上会跑好多个线程嘛。

然后CPU会隔一段时间执行这个线程一下,隔一段时间执行那个线程一下,这个是CPU内部的一个调度。把这个县城扔出去。从 running那状态扔回去,这就要现成给挂起。CPU控制它,这又叫线程被挂起。

听懂这意思了吧,就这么简单啊,别想那么多。就这CPU路到时间了,我可能隔10个毫秒运行,这个隔10个毫秒运行那个。然后10个毫秒呢,我把这个线程扔出去,那个线扔出去,这个线程就被挂起了。

杀死县城算不算臣责?算啊,你县城都结束了,都已经杀死他了。当然算terinated的了嗯。这个线程和操作系统里面的线程是一一对应的嘛,要看你JVM的实现。JVM的以前的实现是一一对应的。

现在是不是一一对应,不好说,最起码县程和里面的线程1%万%是不是一一对应的。所以这个东西呃其实想想看你也没有什么其他的方式。应该来讲啊。我虽然没有读hosible源码,但是在hose body实现里头。

正常应该就是一对应的。Yeah。明记得操作系统里有贪的问状态,你去查一查操作系统里头看。呃,你这个。看你操系统啊,他也现在这个课程呢也在不断的往前进,理解这个状态是什么意思就行了。

time的 waiting就到时间了。加一个定时器嘛,到时间了就会刺激它。okK回去你可以继续运行了,这意思啊。

Yeah。好。我们来看这个小代码啊,在thres类头写了一个小小的代码,这代码呢。呃。怎么样得到这个现能的状态呢?是通过这个现成的gues data这个方法就可以得到这个现能的状态。

Tam start嗯,你比如说你刚开始new了一个thread,还没有启动的时候。那他什么状态呢?回像我刚才讲的那个那个那个那个图,这时候什么状态,new状态,对不对?st完了之后呢。

是runnable状态啊。然后T点join join肯定它结束了,最后是呃ter的状态。嗯,好一好看。嗯,得等他结束啊,612345678910啊,前面那里。

O那么你自己如果想测试呃waiting和tmed waiting啊block的这些状态的时候。呃,像block那个状态,你很难测试出来。为什么?因为它block你那个。在他中间做输出的时候嗯。啊。

也可以你用另有另外一个另外一个线程,正好在它等待的时候输出,必须得正好在这个线程等待的时候,另外一个线程做输出,这时候可以达到得到这个线程的状态。嗯,那我再说一下啊。

这个现程状态啊不是很重要的一个知识点。呃。问到的人也极少,面试问到的也特别少。我们。作为学术上研究,只能说是这样了解就行了。好吧,当然学术研究有好处。你了解了这个形成状态之后,后面我要讲操系统的时候。

其实呢就跟这这个状态呢是一样的。只不过在操系统层面呢,它叫做进程的状态OK。呃,在linux上呢,现程的实现呢是叫做轻量级的进程。所以它和一个进程的区别并不是特别大,它是一个进程的概念啊。

不过状态呢也也就是这些。

系列 4:P33:【多线程与高并发】锁的概念 - 马士兵北京中心 - BV1VP411i7E4

呃,下面呢我来开始讲这个schronous关键字。sch个schron关键字呢,我估计不少同学也是那个耳熟能详了。不过呢作为复习还是要复习一下,好吧。好,第一个呢。是多个县城去访问同一个资源的时候。

需要对这个资源上锁。啊,为什么要上锁?这个概念有没有同学不能理解呢啊,为什么要上锁,必须得上锁?这是一马桶,很多县城过来去访问,必须得等一个县城执行完了,另外一个县程才能执行啊,不然的话呢。

不然的话你自己去想象是吧嗯。O。😊,啊。呃,就是访问某一段代码或者某一个临界资源临界区的时候啊,这个时候呢是需要有一把锁的概念在这儿的。这个锁的概念呢,我估计有的同学可能又会跑高问点。没关系啊。

咱们使劲问啊,我看看我哪哪有问题没给大家准备到位的。什么意思呢?😊,为什么要上锁呢?其实关于为什么要上锁这个概念。估计多少同学也是知道的啊,就举一个最简单的例子呢,我们用一个对一个数字来做递增啊。

这个数字最开始是0两个程序对它一块来做递增。这个递增的就是把这个零的往上加一了。第一个线程,如果两个线程共同访问的时候。第一个线程一读它是零,然后把它加一。

在在这自己这个线程里面的内部的内存里面算算算算啊,0比加个一变成几啊,变成一。然后这个一还没有写回去的时候,另外一个线程来了,一读还是0。读到自己的。内存里面加了个一变成一了。好。

第一个线程把这一写回去了,第二个线程又把这一写回去了。本来正常加了两次,结果呢你最后的结果只得到了一个一。所以。在对这个线程对这个数字进行递增的过程之中,必须呢得上把锁上把所怎么上呢?

就是说我这个线程在对这个数字进行访问的时候。是独占的,不允许别的县程来访问,不允许别的县程来对它进行计算。我必须得给他加完这个一之后,下面这个线线程才能够去拿到这个一之后继续加。

Okay。但是在这儿呢有一个特别特别容易让人。呃,有一个误区吧,应该说而且呢很多的很多的文章里头啊,还有很多老师讲的时候啊,他他就一带而过。我,在这儿呢,我把这个think的。

Synchronized啊。给大家画个图。Yeah。这个think到底think的是什么?呃,我拿我刚才说的这个概念。就这有一个数字一,然后呢两个线程去访问它。那么有有的老师呢就会聊说那个这个呀就是。

这是第一个现程啊,呃这是第二个现程。有的老师六位聊说,这个呢就是把把把这个进行锁定,把它进行锁定。听我说啊。把他进行锁定这件事是不对的,是我们是有一把锁。在这儿呢是有一把锁的。画一下,看能不能画出来。

诶。😊,可以。对也太不想说了。像个狐,好吧,我不管啊。好,我们其实是有一把锁的。听我说,但是这把锁就是说我我我任何的现场去访问这个对象的时候,或者说去访问这个数字的时候,是必须得看这把锁是不是属于我。

是不是由我占有。😊,如果有我占有,我才去对他进行操作。如果不由我占有,我不再进行操作。而这把锁在内部底层上是怎么实现的呢?有的老师会说啊,直接就把这个数字进行锁定,千万别这么谈。

实际上在本质上它并不是对这个数字进行锁定的。它对谁进行锁定了呢?你可以任意指定对谁进行锁定,你想锁谁就锁谁。看这里我的第一个角正易是这么写的。countt等于10,然后让count减减。好。

如果说你想上了把锁之后,才允许对count简减进行访问。比就说我得上把锁才允许执行下面这段代码。那这个时候是怎么做的?你可以new一个object,object O等于new一个object。

然后写schronized的O,这意思就是说对这个countt进行访问的时候,我得去看O这把锁。所以这里锁锁的是谁,锁的是O。但是我们平时也说锁定了一段代码,锁定一段代码的意思是说。

当我拿到这把锁之后才能执行这段代码。

所以要说的比较细致,比较到位的话,应该是这里有一把锁,这个锁是谁呢?是OO这个对象。但是拿到这保所之后能干嘛呢?能执行这段代码。

如果说讲的更加底层一点,我原来讲过一堂公开课。这堂公开课呢叫hsh code与mark word。好,在那条公开课里呢,我讲过这个schronize在底层是怎么实现的呢?其实schronized呢。

在底层的实现没有任何要求,就是java虚拟机规范里头没有规范说 synchronize,你必须得给我怎么实现。不是,他没有任何要求,反正最后的结果不论你怎么实现呢,你只要说必须得加了里把锁之后。

才能执行身份证的代码就OK了。那么hoport是怎么实现呢?hoport是在。一个对象的头上面。这是我们尿在堆里面的一个对象。这个对象的头上面。这个对像头呢是64位。

这个头上面呢有拿出两位来来记录着这个对象是不是被锁定了。是这个它是这么来实现的啊,这个呢叫mark word。感兴趣同学去找一下,看他怎么实现的。他是有两位啊。

两位来实现这两位的组合呢分别是不同的锁的类型。Yeah。好,呃,这是它的具具体的底层的实现。但是呢是需要拿到这把锁之后呢,才去看唉。下面这段代码我能不能运行?所以。锁定。是锁定的某个对象。

不管是哪个对象,你锁定它就行了。那么新能兰这把锁呢呃而且它会有一个所升级的概念,我们一会儿再说。

系列 4:P34:【多线程与高并发】锁的特性 - 马士兵北京中心 - BV1VP411i7E4

这是所得最基本的概念啊,我们来谈一下schronize的它的一些个特性。呃,如果说你每一次都定义一个锁的对象,就是object的 old的给它扭出来,扭出来一个一个对象。那这次加锁的时候太麻烦。

你每次都得定扭一个新的新的对象出来。所以呢有一个最简单的方式就是schronize this。锁定当前对象。就行了。

那么如果你要是锁定当前对象的话呢,其实你完全可以写成public synchronize的这个方法。好。所以,schronized的方法和schronized this。

schronized方法和 synchronized this在this里面在执行这个le它是等值的。

是一样的啊。

那那么大家知道呢,静态的方法。静态方法ttic方法,它是没有那个类似对象的。因为你不需要你有一个class,扭扭出一个对象来就就能执行这方法。那到时候如果我在它上面加一个static的话。

加一个 synchronized的话,这schronize代表的是什么呢?这里代表的是schronized T点class。说到这个TLclass。大家知道那个每一个class文件呀,漏到内存之后呢。

它会生成一个专门的对象,哪个类的对象呢?class类的对象和load到内存的这段代码相对应。所以呢这里的schronized T点class就是锁的是谁呢?锁的是T这个class的对象。

他也是个对象啊,就是class那个类的对象而已,特殊点。

和其他的没有任何区别。

因为。

嗯。

系列 4:P35:【多线程与高并发】设计小程序验证锁的问题 - 马士兵北京中心 - BV1VP411i7E4

好,同学们,我们继续啊。嗯,后面代码呢这前面几个几个小代码也不能我讲的速度呢稍微快一些啊,看这里。呃,我们来分析一下这个小程序,它的输出有没有什么问题。sorry,我这个。啊,是这个啊005。

这小容易的输出。你仔细读一下。Yeah。看着小程序的输出有没有什么问题啊。又有一个thread是吧,然后呢start start呢让count呢不停的剪减。嗯。😊,🤧嗯。Yeah。好。

这小程序的主要的问题在哪呢?主要问题呢有两个,刚才那个我看有同学说没有写vollettail。对。嗯。这是一个啊。呃,但是。严格来讲呢,这个小程序呢其实跟那个what time没有太大关系。

就是另外一个呢,他有可能呃读不到别的线程已经改过的内容,这是很有可能的。除了这一点之外呢,其实它本身还有问题,问题在哪呢?就是这个count减完了之后呢。

下面这个count的输出和你count的减完之后的结果不对,这很容易分析。如果有一个线程从十把它减到9了。然后另外一个线程在第一个这前面的线程还没输出呢,另外一个线程进来了,把九又减到了8。

前面这线能继续输出。就把这个。八给输出出来了是吧,它输出的那个不是不是不是9啊。所以他呃这个呢是有。这样的一些个毛病。那么如果你想修正它的话,你第一个呢是上面加volla条,这边改了之后。

另外一个呢马上得到。除了这个之外呢,其实最关键的呢你还是要在。这里加schronized是吧?这成语比较简单啊,我就不多说了,加schronized。呃,那么我问大家一句。

加了schronized我还用加volat吗?当然现在还没有讲vollatile,所以我简单提一句啊,加了schronized就没有必要加voltile了啊,为什么呢?

因为schronized既保证了原子性,又保证了可见性。好,我们讲volattile的时候再说。嗯,就是这个小程序啊,来看第七个。C007里面的这个小程序。呃,这也是会被有有可能会被问到的。

就是说同步方法和非同步方法是否可以同时调用。哎,什么意思呢?就是我有一方法看见了吗?M1。Synchronized。我调点M1的时候,能不能调M2?可以吗?这个可以不可以,你拿大腿想想,其实就能想出来。

你都不用不用试。这肯定可以啊,必须得可以啊。你本来这个。现城里面。访问访问M1的时候呢,需要加个锁,可是访问M2的时候,我又不需要加锁。所以你还不不让不允许我这行M2啊。😡。

所以问这问题的人脑子都进水了,是吧?开玩笑啊。你本来在这儿。正在运行。啊,你往这一坐,正在运行是吧?你是得上厕所?前面得把这门锁上,这是必须的。可是人家有别的方法,哎,别的方法是什么呢?

人家后面有一擦马桶的,那擦马桶的不需要这把锁,直接就可以擦。是不是?所以你运行这是M1啊,运行你自己的手,这是M1。人家参考桶这事是M2,M2不需要加这把锁,在你运行的时候。

人家直接就可以在后面参考桶啊,没问题。当然呃讲到这儿呢,听我说啊,有很多的那个呃原理性的东西啊,就原理性的东西。还有一些细节上的那些状态的迁移等等。关于这些东西呢,你如果能够写程序去模拟,让它显示出来。

这是一个很好的能力。呃,所以很多时候呢你要去想办法去做这方向的,做这方面的模拟,你能把这个模拟的程序想象出来怎么写,对你也是一个很好的锻炼。所以以后呢有什么别人给你讲的什么的知识。

你都想要想办法呢去写程序模拟它一下,好吧。

只要能模拟出来那,就是一个很好的锻炼啊。😊,呃,不然的话,你只能说老师告诉你是什么,你就认为是什么,你是没有办法做实验去验证它的。嗯,我想那小程序去验证它。这小程序呢。M一是加锁的方法。

然后在加锁的方法里边,MEstar ME end。呃,中间睡了是1万毫秒,然后M2呢是睡了5000毫秒,输出来了1个M2。那么大家你可以想一下,如果说我对M1加了锁之后。它不允许M2执行的话。

那它必须得肯定是M1结束了之后才会显示这M2。如果中间显出来了,那就说明肯定是允许M2执行的。是不是啊同友们。所以我是这么来设计这个小实验的啊。这小时间的设计也比较考验公利的同学们。

所以你们我告诉你们的任何的这种。这种多线程的或者是这个虚拟机的等等各方面的这些个理论上的东西之后呢,你要自己去想办法去写程序去实验它。呃,你比如说我我我说那个你一恋区。对象满了之后呢,它就会产生YDC。

那我怎么去验证它,你得写程序能去验证它,好吧,这其实是比较有功力的。好解这两个小程序啊,你用str T一执行M1。T2M2。运行一点。看结果。T1M1star是吧,你看M2出来了。接下来M一才结束。

说明什么?当然允许人家在后面擦马桶。

啊,这个小程序有没有同学有疑问的?嗯。

有问题是吧?好,继续啊。😊。

好,如果没问题,我们继续。嗯。😊,我们再来看一个schronized的应用的例子啊。这是某拟个银行账户,对业务方法的加锁,对业务写方法加锁读方法加锁行不行?什么意思呢?看这里。

我这里定义了一个class叫account账户,账户有一名称,有一个余额balance name和balance。写方法set给哪个用户。设他多少余额啊。

that their name the name theirbal balance。读方法gebalance通过这个名字去得到这个balance的值。方法呢都相当简单。那好,如果我们给写方法加锁。

给读方法不加锁。会不会有问题?其实这个呢。嗯。😊,好,这个过程呢其实呃。不能说它有没有问题,而是说你的业务呀容允不允许你产生这种问题。如果你的业务说呃我中间读到了那些不太好的数据也没关系。好。

那这个时候呢其实也就没问题啊,如果说你不允许客户读到那个中间的不好的数据,那这个就有问题。正因为呢。我们加了锁的方法和没有解锁的方法是可以同时运行的。同时运行的是什么概念呢?就是说如果有个人啊。

你比方说张三儿,哎,你给他设了100块钱启动了是吧?然后睡了一个毫秒之后呢嗯。去读它的值啊,然后再睡一个2秒钟之后,又又读它的值,这个我需望。要做这个实验的话呢,需要把中间打开啊。set的时候呢。

先设好它名字,然后两秒钟之后再设它的值。嗯。我。才能模拟到这个效果啊。实验一下。就问题呢肯定会有你会你会看到你读到的呢,你本来设的是100,但是你读到了呢是一个0。呃,得到零的原因是什么呢?

是因为呢你那个在设定的过程之中,这点name完了之后呢,你中间睡了一下。然后在中间这个过程我模拟了有一个线程,在这个时候来读。这时候来读的时候调的是get balance方法。

而调这方法的时候是不需要加锁的。所以呢我不需要等你整个过程执行完,我就可以来读到你中间结果产生的内容。那么这个呢现象呢叫做脏读,叫dirty read,叫脏读。如果你想解决这个问题。

这个问题的产生就在于schronize方法和faceschronize方法是可以同时运行的。想解决这个问题怎么办?简单你就把get balance也加上schronized。就可以了。啊。

关于这个小程序,看有没有同学有疑问的。当然我再说,我再强调一下啊,如果你的业务逻辑允许增读,臧读没问题啊,读到中间结果啊,没有关系,我读完了之后,反正我也不做任何重要的业务逻辑,我就读一下,就就O了。

也可以,也没问题,你就不用加锁,能不加锁就不加锁。加完锁之后的效率低100倍,好吧。所以能不加锁就不要加锁。业务逻辑允许不加锁,那就别加。如果不允许就加上schronize。呃。

这个小实验我你们你们下去去复习的时候啊,记住呃。

看着这个面试题来写,你不要看着我的代码来写。你们那个做这个面试做这个题的时候呢,不要拿我的代码在旁边跟这这么来做参考,而自己想象着自己手动的把它写出来。因为你去面试的时候,不可能说你旁边有代码啊。

记住这点就成。

系列 4:P36:【多线程与高并发】锁的可重入属性 - 马士兵北京中心 - BV1VP411i7E4

下面我们来看schronize的等等另外的一个属性。呃,这个属性是什么呢着?这个属性叫做可重入。这可重入也是 synchronize必须的个一一个概念啊,不然的话呢就没法使用它了。

simized叫可重入。可重入是什么概念呢?如果说一个同步方法调另外一个同步方法,有一个方法加了锁了。另外一个方法也需要加速,加的是同一把锁,也是同一个线程。那这个时候申请仍然会得到该对象的锁。

比就如说signronnet可重入的什么意思?

有一方法,M1它是 synchronized,有一方法,M2它也是 synchronized的M1里能不能调M2,可不可以?如果它不可重入会产生什么现象,你分析一下。Schronize。

我们M一开始的时候是这个线程得到了这把锁。然后在M1里面调M2。如果说这个时候不允许任何一个线程再来买这把锁的时候,就死锁了,这是不可能的。这时候如果再调M2的时候,他发现还是同一个县程。

因为你M2也需要申成这把锁,结果他发现调M2的时候呢,我需要申请这把锁的时候,发现哦,原来是同一个县程申成的这把锁,允许。可以,没问题,这就叫可重入锁。所以 synchronized的是可重入锁啊。

synchronized的必须是可重入锁。以前有个同学会被问到问到了面试的时候问到了这么一个问题。呃,simcherronize是可不可重入的,为什么?它必须是可重入锁,原因是什么呢?

你比方说你有一个负类。哦。Parent。它里面有个方法,M有一个子类child,它里面有个方法,M重写了它,但是呢它掉了super。点儿M。如果你上面是schronized的。

OK这里也是 synchronized。你说掉super点M,这个很正常啊,我调腹类的这个M方法。但是如果它不能够重入的话,你就直接父类父子类之间的这种继承就直接死锁了,这肯定不行。

好了。

这是sful可重入的概念。

嗯。好,看这里啊。

嗯,这个呢就是我刚才模拟的一个负类子类的概念,负类 synchronized是吧?子类你标用C点M的时候,必须得可重入。如果不可重入的话,那肯定出问题了。调付类还是同一把锁吗?必须的呀。

你看schronize是锁的谁啊,锁的this嘛,this就行。

这个signchronize也说的是this似对象目嗯。

还是同学要锁啊,估计有同学可能会在这儿有疑问说我这个schronized的到底锁的是副类的face对象还是子类类对象?我记得我原来画那个父子类的这个图的时候,你扭出来这个对象叫TP。

在它里面呢有两种方式啊,第一就就基本上就只有这这种实援方式吧,就是它有一个。他有一个那个那个呃parent的这个指针指向的是他的负类的对象。但是锁对象的时候,你想想看。你掉的这个方法。

symronized它锁的是谁,锁的是this,这个地是谁啊?这是他嘛。对吧。当你调跑到这个方法去调的时候,super点M它锁的还是叫this嘛?this次还是谁,还是他啊。

所以锁的是同一个对象啊。呃,所谓的重入锁就是那个你自己拿到这把锁之后,自己不停的加锁加锁加锁加锁加好几道,但是锁的还是同一个对象,还是你自己锁的。你去一道就减个一,再去一道。

再减个一这么一个概念比较简单。

系列 4:P37:【多线程与高并发】异常跟锁 - 马士兵北京中心 - BV1VP411i7E4

Cha。啊,如果没问题呢我们来看那个异常跟缩啊,这个也是也是需要你小心一点的概念。这异常跟锁的概念异常跟锁的概念是什么意思呢?就程序之中,如果出现异常,默问情况下锁是会被释放的。再说一下。

记住这一点就行了。程序之中如果出现异常。默认情况下,锁会被释放。

Yeah。

好。不。看这个小程序,加了索schronize voiceMYl不断执行现程启动。

看的佳佳。嗯,等come呢s。如果come能5的时候,我让他人人为产生了异常,I等于一除以0,这肯定会产生异常除零异常。所将被释放。如果不想释放。让循环继续。本来我们是well true一个服务器程序。

在这里不停的运行。

然后呢,还加了锁 synchronized的别的方法进不来。这个时候你如果产生了任何的异常的话。

O中间产生了任何的异常,就有可能会被什会产生一种什么情况呢?

会被原来的另外的那些个准备拿到这把锁的程序。

乱冲进来了,乱入程序乱录是吧?本来。我要执行下征证证代码,要拿到这把锁。哎,但是呢我中间产生了异常,然后我就把这锁给释放了。另外的所有的那个程序,哎,正等着往里头运行呢,马上我就拿到这把锁。

有可能会对你的数据产生一致。

好,这个叫做异常会释放所。所以一个web application的处理过程啊,多个serv线程如果说共共同访问同一个资源的话,异常处理不合适。抛出异常之后,其他的就有可能进到这个同步区。

会产会访问到你异常产生去出的那些中间的那些数据啊。这要非常小心。嗯,这我就不演示了,好吧。本来你看上面这个线程O要处嘛不停的运行啊,但是一旦抛出异常之后。这个就会被其他县城所运行了。上面呢是我们的。

T小T等于6T。T点M都是叫T点M方法。那么第一个线轴呢是。去调它的T点M方法。嗯。😊,第二个线程是T2,也是调T点M方法,输出的呢是每一个线程的名字。本来正常情况下是T一运行,T2不可能运行的。

不过呢,它一旦产生异常之后,T2这可能运行。来看一下结果。T4。2的啊。你看你这里产生了一个异常。by zero结果马上T2就得到了执行执行结果了,看到了吧?得到了执行的机会。

啊,你的程序呢本来正常是不允许他执行的OK。好,这里呢是异常和锁的概念和schronize的这个概念。

系列 4:P38:【多线程与高并发】锁的底层实现 - 马士兵北京中心 - BV1VP411i7E4

Yeah。好,看这里啊。

ok同学们呃,那么讲到这儿呢,我觉得有必要呢跟大家谈一下就schronized的这个具体的底层的实现。

对。

啊,看这里,我那个建了一个新的package包啊,C001-01,我觉得我好像少跟大家谈了一点小问题啊。我把这个sronnet的具体的实现在这呢跟大家交代一下。这个sronize的具体的实现呢。

有他经历了好几个阶段,可以这么说啊,就原来呢。最早的时候啊,在JDK比较早期的时候吧,这个也不太记得到底是哪个版本了。总而言之,是这JDK比较早期的时候。Yeah。这个sim的实线是重量级的。

schronize实际验是非常重量级的,它所谓非常重量级的一个概念是什么概念呢?就是它这个schronize的都是要去找操系统去申请锁。然后就会造成schronnet的效率非常低。

后来呢嗯就是要加va后来越越来越开始处理那些高并发的这些方面的职业程序的时候,很多那个成员就特别不满意,说你schronize这个方法这些简直用的是实实实在是太重了啊,我我没办法,我就得开发新的框架。

我不用你原原生的了。后来做了一些改进,后来的改进,后来改进成什么样了呢?其实simize呢是有一个所升级的概念。关于这个所升级的概念啊,我还专门写过一个。文章叫做我就是厕所所长。大家去找一下啊。

我的我的那个公众号里面也有。呃,然后那个网上你搜一下啊,应该网上也有啊,两个,一共是两个,一和2。啊,我专门用小说的形式讲了这个所升级哎,到底是怎么样的一个概念。呃,我不带来家读了,好吧。

两篇文章还是有点长的啊。在这里我跟大家交代一下,这个所升级是什么概念呢?这个所升级的概念呢是这样的。呃,原来呢都是去找那个操都要找操作系统,要找内核去申请这把锁重量级的。到啊折基是1。51。5之后是吧?

嗯,好,到后期呢进行了一些对simronnet做了一些改进,它的效率呢变得比原来要高少。改进在什么地方呢?当我们使用schronnet的时候,hospot的实现是这样的啊,上来之后第一个。

去访问某把锁的现程。你比方说schronize的某一个。F it。上来之后呢,先在这个object的头上面。mark word记录这个现场。就记录一下这个现成的。写现成号就行了,就往这个O上一记录。

什么也不干,没给他加锁。我再说一遍,如果只有第一个现程访问的时候,实际上是没有这个给这个O直接加锁的。在内部实现的时候,只是记录这个现成的ID。Yeah。这叫什么呢?叫偏向左。

所以偏向组的概念就是说你你是我的第一个,我偏了你一些。我默认将来呢不会有来第二个县城来来抢这把锁。好。O。这个时候使用的是偏向锁,只记录这个线程ID效率非常高。如果还是这个线程回来访问,哎。

一看这就是我的那个对象得嘞,我也不用申请什么锁了,乱七八糟的了,我直接开始执行就完了,所以它效率非常高。而且大多数情况下呢,也都是一个线状来执行啊,这是偏向锁。然后偏向锁如果有。现成征用的话。

如果有现成征用。去。好,这个时候就升级为什么呢?自选锁。自悬锁什么概念?自选锁的概念就是哎你蹲在马桶旁边,这哥这个有有有一哥们儿在这蹲马桶了,对不对哎。我哥们在这蹲着马桶呢。好,另外来了一个哥们儿。

他干嘛呢?他在旁边等着他不会去跑到那个我刚才说的那个CPU上那个就绪队列里面去,不会,他就在这等着占用CPU用一个well的循环,welll true是吧,之类的,类似的这种循环。

在这转圈玩转了好多圈之后,发现这哎哥们你还不行了。得这种情况下,整个锁才会再进一步升级。好,自权所悬默认的情况下是悬多少次呢?是选1次之后。两个县程,一个县程在那占着锁。

另外一个线程跟他自悬悬了10次以后。如果还得到这把锁。升级为。可以。重量解锁。所谓功能机锁就是去操作系统那里去申请资源,再加这把锁。啊,这里呢是经过一个所升级的概念。有了这个新生代的改进之后呢。

原来曾经有一些个文章哈,还有一些那个其他的那个那个那个啊讲法也好,说说这个schronize啊比atomic原子类的那些操作慢不少啊等等这样的一些个说法。啊,但实际上我告诉大家。

经过了这些个所升级的这些概念之后,schronized用的偏向锁自选锁,然后呢重量级锁。你你如果做测试的话,你会发现大多数的情况下,schronized并不比那些atomic慢。原子类哈不不比那些慢啊。

😊,好了。😊,所以这是一个所升级的过程啊。好,看看这一小块呢,有没有同学有疑问的地方。折子记说好像还有1个CAS的过程,大哥自选锁在干嘛?october自悬10次不也站在CPU,别人也释放不了锁呀。

如果释放不了,再去升级为重量级锁的时候,这个线程就成为等待状态,就不占CPU了。october。啊。啊,锁好像只能升级,不能降级。对,没错。是的。缩耗像是没法降级的嗯。哎。

jo的是你你提的这个问题还是很尖锐啊。这说的非常的非常的到位啊,就是说。你本来这个锁大家伙的征用征用来征用去。哎,然后呢它升级为重量级锁了。升级为重量级锁之后呢,后来这个征用下来了。

就只剩那么一两个线程了。这时候呢如果你再回来效率会更高,但是呢你回不来了。其实能不能回来。我想啊如果你的你的虚拟机实现写的到位,也可以做到能回来。我再说一遍,synchronize这个东西。

java虚拟机实现里面并没有规定它到底该怎么实现。所以我说的这些全都是hospot实现。就oracle的这个虚拟机的实现。假如orle虚拟机实现不是这么实现的,我也没法给你这么讲啊。嗯。😊。

Otober感觉自学没有用啊,你再感觉感觉我给你。3分钟4分钟5分钟之后啊10分钟之后。如果你你再感觉感觉,如果你还不能不能理解,我再讲给你听。嗯。😊,自选组啊。呃,既然讲到这儿呢,我们讨论一个问题啊。

在什么情况下?我们使用自选锁比较好,因为atomic以及包括后面的很多锁啊,这各种的lock。其实他用的呢全都是那个自悬锁。用的自选锁基本上用的全都是自选锁。这个特收不有一个特点,它是占CPU。

但是它不访问。操作系统。所以呢它是在用户态,在用户态去解决这个锁的问题。它不经过内核态。因此,它的效率上,这个加锁和解锁这个效率上其实要比那个经过内核肽这个效率要高。哎。

但是呢你分析一下在什么情况下用自悬锁会更好一些。在什么情况下用重量级锁会更好一些。经过内核的要要要好一些。你们分析一下。在什么情况下呢?自选锁由于它是要占用CPU的,而OS这把锁呢实际上是不占CPU的。

所谓的不占CPU的意思是说,在旁边竞争的那些个线程是进入的等待堆列里。等待堆列呢就是说你在那儿等着不占CPU什么时候CPU让你运行了,你才把你把你叫起来,你才运行。所以什么情况要用自己选锁。

什么情况要用这种锁,你分析一下。执行时间长的用系统锁没错,说的非常对。这个问题你们要好好思考。像这一个问题,如果在面试的时候,能跟面试官谈清楚,肯定会高看你一眼啊。没错。啊。

这writerder说的非常对啊,执行时间长,尽量的用系统锁。执行时间特别短。另外,除此之外,执行时间除了短之外。你的这个县程还不能太多,2万个县城跟这等着自选。我告诉你。

这事儿也受不了一个县城在那执行19999个在那自选,你觉得你CPU受得了?Yeah。所以。是执行时间比较短,这是第一点,就是说加锁代码执行的时间比较短。他别人经过就十四字悬。

这个别的那个锁可能已经做已经拿到了。好,在这种情况下。直行时间短,县城数比较少,用自选锁。执行时间比较长。现程数呢比较多,用系统锁。Oh。

O。Yeah。把这个个给大家写出来啊。这里指的是加锁代码啊。用自权。执行时间长。小能鼠多。用什么?系统走。就是你用syronized的就这意思啊。Okay。好,4分钟也过了啊,刚才那个。

刚才是谁我问你了,october是吧?凹小鬼懂了是吗?好,很很好啊,good。😊。

嗯。😊。

系列 4:P39:【多线程与高并发】day1课后总结 - 马士兵北京中心 - BV1VP411i7E4

好。呃,我们呢稍微回顾一下今天讲的内容,好吧。

や。你稍微就回顾一下今天讲内容啊,今天呢实际上就讲了哎到底什么是现成,对吧?现成的概念。启动方式。嗯。常用的方法,sleep join。常用方法。嗯。然后呢,我们讲了现状。同步的概念。

主要讲的是什么辛苦。我们稍微回顾一下这个 synchronize到底什么意思。首先,schronize锁的是谁呀?锁的是一个对象。锁的是对象,不是代码儿。这是必须要搞清楚的。第二一个呢。

如果你在一个方法上,如不加任何锁的话,锁的是呃不加不加任何指令的话,锁的是this。好,呃,除了这个之外呢,你可以锁静态的,锁静态的锁的是什么?锁的是什么什么点class,是不是锁这个类。呃。

还有一个呢就是schronize呢是锁定方法和非锁定方法。可以同时执行。O。呃,除了这个概念之外啊,就是所升级,它本身有一个所升级的概念。所升级呢是经历了三个过程啊,第一个过程呢是偏向左。

这所就是那个你来了之后,我就进你个号就行了。哎,开门还是你还还是你,那你就进来这意思。第二个呢是自悬锁。我先不尝试去找操系统申请那个大锁,先申请这个小锁,先自己悬着在旁边转圈玩。然后呢才是重量底锁。

就是向操作系统申请的重量底锁。然后呢,我给大家讲了,在什么情况下用自悬锁,什么情况下用重量去锁啊。OK这是我们今天讲的内容。呃,sorry啊,我想起来了,我少给大家讲了一个小问题。

就我讲一什我少讲你什么问题呢?呃,锁定。就schronize。你锁定这个对象的时候啊,这个objection。不能用什么。不能用screenring。不能用integer吧。

不能用long这些基础的数据类型。不能用s string的概念,主要是什么呢?因为呃不能用s string的常量,严格来讲应该是这么说。你尽量的连那个连对象都不要用就行了。不能用时间常量。

为什么不能用死针常量啊?你分析一下,如果你simronize的有一个,比方说是sronize的是这么一个玩意儿。是这个对象。增这常量。那字符特常量大家都知道那个所有用到这个字符特常量的地方。

其实用的都是同一个,对不对?好,假如你某一个县程锁定了这个字符串常量的话。而且很不幸的是呢,这是一个内库,一个library。别人用的一个炸包里面,你写的某一段程序,你锁定了这个字符串常量。

然后你的用户的现成的人呢又尝试着去锁这个字符段长量。结果就会发生什么呢?用到这个内库的那些个代码,哎,不小心给给这个给锁定了。结但是呢当你用到这个内库的时候,又需要锁定这个。

你发现你一不小心别人写的代码跟你写的代码之间竟然锁定的是同一个对象,中间会产生什么奇怪的现象,我就不知道了。Thank。方下也不自得说重入了,你你给我哪凉快,哪待着去。😡,重入一定是同一个县程啊。

sorry,你你我我我我连我打两回哪来行这个也有可能你跟你用到那个内裤的确实是同一个线程,但也有可能不是同一个县程。如果不是同一个线程,很可能就死锁了。如果是同一个县程,很可能重入了。

重入了也不一定是想你想要的那个结果。😊,所以记着这一点就行了,你不要用这个磁针长量,也不要用integer。因为inageger它内部做了一些特殊处理,你每产生这个integer。

只要那个里边那个对象稍微变一下那个值,它就会变成一个新对象。OK所以。记着这个结论就行了,不要用死针常量,不要用这些基础的数据类型。听懂了吧?所以就别废话,你就那个别用这个就OK。

系列 4:P4:【JVM调优实战】对比:rust为什么不需要GC - 马士兵北京中心 - BV1VP411i7E4

没有一种语言。运行效率又特别高。Yeah。运行效率。超高。对标的是汇编C加加。不用手工管理内存。Okay。没有DC。OK恭喜你啊,现在他已经诞生了,这个语言叫ras。但是他也有他的毛病。学习曲线。居高。

Okay。这是rest。呃,有同学非常的好奇,说老师这事儿很神奇啊,运行效率特别高,what跟C和CI加差不多。然后呢,你你你只管自己去往内存里头分配就可以了。你不用管回收,没有GCA。😊,哇。

他是怎么做到的呢?😮,ra子没听过是吧?你落你太落伍了啊,你是这行业混的吗?你稍微稍微关注一点最新的技术的发展。大哥。希望大家伙的学习叫做与时俱进。嗯,这词儿呢非常的重要啊。

就是你呢学习上一定要与时俱进。咱们入了这个行业,你要想不学习,就能持续不断往往前发展。不可能的那你是温水煮青蛙把你自己慢慢煮死。😊,好吧。好,大家看这里啊,这个rest呢是比较新的一个语言。

它的特点就在于这儿它运行效率超高和C和CI加差不多。但是它开发效率呢也并不低,原因是什么?原因是你不用手工去管理内存,你只管去分配就行,你不用管回收牛刀吧。好,他主要是怎么做到的呢?你想听吗?

今天其实主要讲JVM的GC的,那顺带的给大家讲一讲,好吧,来。😊,看这里我我我告诉大家一个特别他特别特别牛的一个概念,他特别牛的概念叫什么呢?叫ownership。Yeah。

叫Eership叫所有权所有权的概念。这个所有权概念是什么意思呢?所有权的概念就是这里面的每一个值。

Rust。Okay。呃,就是这里面的这这这这个这个这个这个任何一个值啊,任何一个值都归属于一个变量。就是一个变量代表一个值,一个变量指向一个值,任何一个值都归属于一个变量。

然后有且只有一个,不可能有多个。这句话什么意思?我形象一点解释。我告诉你,在这张图里面,我们会有多个变量好,这叫一个变量O是一个P是一个啊,这里O是一个P是一个好。

有多个变量指向同一个值或者叫同一个对象。在rat里面,这件事情不可能发生。哈哈,听懂了吗?我再说一遍。格浪的GC讲讲格浪DC是接近于。java语言里面的ZBC的一种算法接近于它啊类似。好的。

看这里我再说一遍,重新重复一遍。就是多个变量指向同一个对象,这件事不可能发生,只会发生什么呢?同一时刻只会有一个变量指向这个对象。这就是所有权的概念。叫做。我们这个值的所有者只有一个一夫一妻制。

好不知道大家听清楚没有?😊,那有同学可能就会说了,老师这有什么好处吗?😊,来,你们拿大腿想一想,小伙伴们,假如我在战空间任何一个战争里面的变量。纸箱的这个空间。如果确保是一夫一妻之的话。那我这个。

我们叫她丈夫吧,她的丈夫消失的时候,他的妻子是不是顺带着就殉情了?听懂了吗?再说一遍,她的丈夫死掉的时候,什么时候死掉,还记得吗?他的妻子就跟着殉情。自动就给你回收了,你发现没有?没理解是吧?

听我说还记得占空间里面它的特点是什么?占空间特点是当我这方法结束了,我这占空间就不存在了。我这方法结束了,占空间不存在了。哎,我们假设。如果这个P你已经确定它不存在了,同时是一夫一妻一妻制。

没有任何其他人指向这个对象,你们好好想想看,我这个对象是不是就可以回收了。方法结束,占空间里变量指向的任何空间跟着回收就可以了。听懂了吗?也就是说我不需要GC为什么不需要GC大哥,你你这边你这边消失了。

我给你加几行代码,把这个里面关联的编辑器帮你自动加的啊,关联的内容OK直接就给你干掉了。所以。😔,这是ra的它的一个核心的设计理念。ra的这个特点诞生之后啊。

同时在堆叠加了它的这种对于多线程访问的呃共共共共享变量,必须你得你得需要采用它特定的书写机制才能够写的出来。它会产生了一个特别奇妙的东西,叫做你写不出bug来。好。说一下啊。😊,这是ra的语言。

特别有意思的地方叫做。😊,Yeah。Okay。不知道大不知道大家听清楚没有?😊,你只要程序的语法能够就不会有bug。当然它语法非常的特殊。这讲着讲着怎么讲成ras了?Yeah。嗯。

逻辑bug是任何语言都存在的,任何程序都躲开了。大哥,逻辑bug是啥?你本来让你计算这个程序的一个人的年龄,你给计算成什一计算成为一个人的体重了。啊,本来让张三娶了李四,你非得让他娶王五。

那这种bug我你你这跟语言有半毛钱关系吗?是吧。所以这个语言没关系啊,咱们说语言层面的bug,ra呢消给你消失消了很多。

除了我刚才说的这个ownership之外,除了还有呢就是在多线程的这种写法,多线程写法叫做固定的,你知道吧?你就得这么玩,你不这么玩的话,你根本写不出来。😊。

你想让多个县程去访问同一个值吗?我告诉你,你只有这种写法,你不用这种写法,你根本就写不出来。所以只要你写出来就没bug。就是这么的牛叉。啊,我不知道我大概说清楚没有啊,但是咱们今天还还是得说来啊。

今天并不是讲ras的。

嗯。不感兴趣。对啊不感兴趣算了嗯。反正你们对新的东西也不太感兴趣,你们讲老的吧。🤧。讲这VM啊好了,这是语言的大概的一个发展的历史。你要你要明确啊,现在这个语言呢大概分这么多类。那有同学说老师。

那GS这种东西是什么?其实这这些都是带垃圾回收器的,好吧,就GS这些啊,还有像什么还有还要像其他的啊,这coldline的等等,这不说了,它本身就是运行在这VM上的,所以它肯定是带垃圾回收器的啊。

还要像什么scalecal。😊,啊,就老师给你讲东西呢,我希望讲那个层面太低了。我希望站在更高的角度上来教你认识啊,就整个。1个IT界的一个发展。还有呢整个语言上的一语言层面上的一些东西。

你站在更高的一个角度上啊,建立起来你的知识体系O。ras有啥缺点?ra缺点就是学习曲颜值高嘛,特别高嗯。好同学们。想太多了是吧?嗯,已经9点了,what确实是啊我们来聊聊那个JYM的这C的历史啊。

疲惫了是吧嗯。A了已经疲惫了,不会吧,你你们还活着吗?我们可以继续吗?这还没开始DC呢,没开始也没开始吧。就业怎样?就业不怎么样?因为rest刚刚发展,我们静观其变。

我是喜欢让我们自己的学员都站在业界的最前沿。就是你要抬起头来看看整个行业发展。站在整个业界最前沿,你就能发现更。更加优秀的机会。发生机会的时候,你能扑上去啊,做好准备。

系列 4:P40:【多线程与高并发】day2课前复习 - 马士兵北京中心 - BV1VP411i7E4

OK不多说了,我们稍微回顾一下上节课我们讲的多线程和高并发这方面内容,回顾一下啊,讲了线成的概念,这非常简单,启中的方式。嗯,你有一个thread start。用runable来启动。

用executor来启动。常用了一些方法,sleep wait join。县城如果需要同步加synchronized。schronized不能用常量。不能用tring类型的常量啊。

不能用基础数据类型、indi long等等。哦。线轴的臀步。它呢锁的是对象,而不是代码,这一定要记清楚。你锁的是某一个对象,是通过这个对象的对象头上面的两位来控制是不是加了锁,加了什么类型的锁嗯。

锁呢一般来说默认的会有锁this锁当前对象锁。什么什么的class所整个这个class类的对象。什么时候呢?如果你是普通的方法,schronized的M普通方法锁的是this。

如果是static synchronized的,那么锁的就是什么什么点class。锁定的方法和非锁定的方法是可以同时执行的。非锁定方法人家本身就不需要去访问这个锁。所以呢你锁不锁跟我没有任何关系。

所以你要想如果说你的某一个类想支持类行多线程的话,你得特别特别小心翼翼的来进行设计。呃,什么样哪些方法要加锁哪些方法呢?不加锁。所升级的概念呢就是schronize的内部呢进行了一些相应的优化。

所升级的概念我们来稍微回顾一下。这个从阿里的这种面试的变态来看的话呢,这种题后面也会慢慢的会被问到。什么叫所升级的概念呢?所升级的概念就是嗯你比如说你要锁定某一个对象,那么前面我说过。

我说在这个对象头上的某两位。来指定它到底锁的什么类型的锁。在对像头上还记录着当前现城哪个县场啊,哪个县城申请了这把锁。那偏向锁的概念是什么呢?这线程来了之后呢,先不尝试给它进行加锁。

只是记录这个线成的ID值,线程ID记在这儿。那么我们就认为呢这个对象呢是这个县城独有。下次再来申请这把锁的时候啊,他就会认为就是那个那个倾向于还是这个这个线程。

那就是说这个锁呢实际上是偏向于这个第一次拿到这把锁这个线程的,所以他没有真正的加锁,它只是说你下次来的时候判断你如果还是原来那个线程呢,就你就别加锁了,继续直接访问,不要考虑这个加锁的问题啊。

因此呢效率上会稍微高一些啊,但是如果来的县程,新的这个线程呢,不是原来那个你发现新的这个线程ID和原来这个线程ID呢,它不等在不等的情况下怎么办呢?进行锁升级。进行锁升级。

锁升级呢首先会尝试进行自选锁的升级。什么意思呢?从偏向所升级为自选锁自选锁呢?就是说呃如果说这个线程在这已经拿到这把锁了。那么另外一个线程来了之后呢,跟着转圈。询环。Well。哎,我能不能拿热么锁啊。

能不能拿这么锁啊,能不能拿热么锁啊,跟这转圈,转十圈,默认是这个值是是转十圈,如果拿不着,这时候干嘛升级重量级锁。这哥们儿就去wait了,大家知道重量级锁的概念就是说经过我们的OS,然后进入等待队列啊。

进入在等待队列里头。进入等待队列之后呢,它就不再占用CPU时间了。所以它占用CPU时间,占用时圈,时圈完了之后呢,就进入等待队列。什么时候用自选锁,什么时候用重量你锁呢?嗯你你你还还记得吗?

如果说上节课没听你好好你考虑一下这个问题。根据自选锁和重量级锁的特点,什么时候是自选,什么时候重量级锁。自选所咱们说线程数少的时候,线程数偏少的时候使用自选还是用重量级比较合适。如果其他条件都一样。

这肯定是自选。没错,这大家都很这很很很很很简单,宣投数少,你选两下呢消耗的时间也不多。但是如果现成数特别多,你跟这自权还有意义吗?2000个县城,一个县城在那儿。厕所上蹲着2000个县城在旁边转圈。

你盯得住吗?这肯定不行。所以一个是哎这给大家写一下吧。自学叫做积极的排队啊,它是占用CPU时间的。如果你是为它队列呢,哎,它就不是不占用CPU时间搁那等着啊,消不不消耗CPU的。所以如果现成数少。

这个呢平该是偏向于自悬。如果多的话呢,应该是偏向于重量计算。只有一在那儿跑就行了。那我再问你。呃,大家知道你拿到这把锁之后要执行操作。如果这个操作的消耗时间长。来告诉我用自学还是用重量激锁。考虑一下。

不量解锁。是不是?

系列 4:P41:【多线程与高并发】Volatile保证线程可见性 - 马士兵北京中心 - BV1VP411i7E4

dmon就行了。现场有一个方法叫set demon设成 true,自己去查thread类里面的一个方法。okK我们呃唉。下面我们来看这个volattile的概念啊,voltile到底是什么意思?呃。

vololaile呢我我们直接来看程序,来看这个小程序啊,vololaile也是面试。现在现在像那种大的互联网企业的面试。

基本上额了条是避会的。呃,那么他有时候也不太问了,因为他认为呢你应该会。呃,所以你会不会呢?他也他也不问了,但是呢像那个呃中小企业呢,他也开始问这方面的问题啊,窝了条那窝了条到底是什么意思呢?

来我们来看一下这个小场序,你就知道了。看了小程序,小程序呢我写了一个方法啊,先首先定一个变量,布尔类型running等于tru。说现在正么在正是不是正在跑着呀?是的。然后呢,我们唉写了这么一个。

这么一个一个一个方法啊,这方法呢是哎上来之后呢,我输出M start。

然后while running while running的意思是说,哎,如果说正跑着我就执行我的操作。这里模拟的是什么呢?模拟的是一个服务器的。服务器的操作。大家知道那个不管是什么样的服务器啊。

游戏服务器也好,ATP服务器也好,这些服务器呢一定是说在没有停止的情况下,它就在那7成24小时不间动的运行。什么时候让它停止,你可以点它一下,可以强强制的杀死它。我就模拟了这么一个操作。

这个操作呢用一个波尔类型的变量来指示你要不要继续运行。如果这个值为处,那么你给我不停的监督的运行,我什么时候把这只fose,你就应该停止了。这里呢是一个非常理想的情况。

我什么时候就把这值设成forse,你就应该给我停止。所以这时候你应该输出M end。

ok好,大家看这里啊。我的方法是怎么测的呢?我我来进行对它进行测试。因了一小T,我就不说了,newth。起了一个线程,这线程呢调用了M方法。好,这个写法同学们没有问题吧,有问题同学给老师扣1。

后面林老师在初级里头,我给大家讲了咱们的表达式。这是lembber的表达式啊,lambber的表达式相当于是我new了一个thread。因为有同学有问题啊。这是lemb表达式的写法。

相当于呢呃是这么写的,new了一个thread,扭了一个reable。然后在这ranable里面呢,大家要知道它要重写run方法是吧?在run方法里边直接调用了M,就是这个意思。O。哦,sorry。

这是我的问题啊,有问题扣一,你扣到12sorry。😊,我的问题啊。啊。我那我就不多说了啊,然后呢扭了一个现程start。好,睡了一1秒钟,睡一秒钟之后呢,我把这个值设成false。那就是理想情况。

你把这个值设成false之后,理想情况。这线程应该就停止了,这线程停止的话,它就应该输出M end。我们来运行一下,看看是不是它会停止啊,看一眼。你看Mstar啊,你就数吧。

一秒钟、2秒钟、3秒钟、4秒钟。你数多少秒,这哥们儿呢就是不停。但是神奇的是呢,你只要把reent打开。哎,如果这里呢我们。修饰这个变量的时候加了volat volatile。运行。M star好。

一秒钟之后MN。OK咱能理解这意思吗?你加老公的条。😊,这这个它就能准确的停止。如果不接,它就停不了。okK这这就是vololatile,它起的作用。那vololatile到底起的什么作用呢?好。

vololaatile本身的含义呢叫做可变的易变的,容易产生改变的那意思就是说这个值啊是可变的,你得使劲的跟踪这个值。什么时候它发生了变化,你要好好跟踪它。好,你认真听,今天呢来聊这个vollock啊。

🤧大看这里。word要聊起来呢,它有两个作用。第一条作用呢叫做保证现成可见性。第二条作用叫做禁止指令重排序。大家给我记住了。由于面试场考,你也啥话也啥也别废话,给我记住就行。保证现程可见性。

禁止指令重排序。不是实时监控,听我说。看这里。保证现成可见性指的是什么意思呢?指的是这个意思。我呃讲过很多次呢,这个现成的概念呢。呃,JVM呢我们是讲完这个这并发之后才讲JVM啊。

所以如果有同学没有听过的话呢,我简单给你解解释一下。大家知道java里面呢是有堆内存的嘿。多内存呢是所有的现程共享里面的这个内存。这是呢所有县城共享的内存。除了所有县城共享内存之外呢。

实际上呢每个县城都有自己的专属的区域,都有自己的工作内存。如果说在共享内存里面有一个值的话,比如说像刚才我们的running,它等于true啊,或者等于fose啊等等。当我们县城某一个县城。

这是我们的主线程。这是我们的T一线程。好,这两个线程都要去访问这个值的时候,他们会把这个值科py一份。copy到工作性自己现成这个工作空间里头,然后对这个值的任何改变,首先是在自己的空间里进行改变。

比如在这里呢,我把它变成了false。但是这个fors什么时候写回到主共享内存里头?不好控制。我再说一遍,什么时候写回去。不好控制。O。是。所以你刚才看到它什么时候写一下,这玩意儿不真真的不好控制。

除此之外呢,还有一个呢就是这个well使用flag的副本这块的内容。那他什么时候他已经拿到这个副本了呢?它will不断的循环,不断检查他什么时候再去检查这里面有没有新值啊。也不好控制。那好。

如果你对这个变量不加高了,它就这种情况,它什么候写回来,我不知道什么时候读这个新的有没有改改过的这个纸,我也不知道。啊。No。呃。对不起啊,我感觉什么时候读是不知道的,什么时候写的话。

应该是你改完之后会马上写回来。改完之后会马上写回来啊。这个sorry。这我要查一下啊,应该是改完之后马上写回来,但是什么时候读是不知道,但是不管怎么样啊。在这个县城里头,它会产生一个现象。

就是在这个县程里头对这个副本进行了更改。并没有及时的反映到另外一个县城里面。okK并没有及时的反映到另外一个县城里面,这个就叫做县城之间呢不可见。县城之间不可见啊。好,那既然县城之间不可见的话。

你这个县城里头改变另外一个县程就不知道。我刚才是在没县城里头把它设成foralse。那么我在提这个县城里头,他什么时候看见这foralse,他不知道。对,这个变量值加了vol了跳之后。

就能够保证一个县城之间的改变,另外一个县城马上就能看到。这是vololaile。What头。它本身如果我们说的再细致一点的话啊。听我说,我不知道会不会考到这么细啊。

其实现在这种这种这种变态的考试越来越多了。请大家去查这个词叫如果没记错的话,MESI。呃,这个是它它的本质上是使用了CPU的一个叫做缓存一致性协议。CPU的缓存一致性协议。缓存一致性协议啊。

我刚刚想起来。呃,大家去分析下,就是多个CPU之间,它也需要对进行一些个缓存。由于你不同的线程是不运行在不同的CPU上,所以这个CPU里面的这个副本改了,另外1个CPU不一定马上就能看得到。

本质上呢它这个。他呃。这个概念上是一样的。但是呢你java里面这种线程之间的可见性,实际上要靠CPU的缓存一致性协议,你才能够保证你你你你你能得到这个值。不然道你考虑一下,它中间写回读取的这个过程。

如果在读取的这个过程之中,又有人改了又怎么办?所以归根结底是要靠硬件来帮我们实现了。

系列 4:P42:【多线程与高并发】Volatile禁止指令重排序 - 马士兵北京中心 - BV1VP411i7E4

那么窝外条还有一个很重要的,它的作用是什么呢?叫做禁止指令重排序。那么禁止指令重排序又是什么概念呢?听我说我们先说指令重排序是个什么概念?指接重排序呢。如果往深里挖的话,也跟CPU有关系。也是跟。

现代的CPU是有关系的。那么你去考虑一下啊。每次写都会被现成读到。对每次写都会被现成读到,加了vol条之后。呃,这个指定铜白具呢。如果往细节上抠,它也是和CPU有关系的。

CPU呢原来执行一条指令的时候啊,它是那个就一步一步的顺序的执行。但是现在的CPU为了提高效率,他会把指令呢。并发的来执行。这是第一个指令指令的执行到一半的时候。那么第二个指令就可能已经开始执行了。

第三个指令就可能开始执行了,这叫做流水线式的执行。都是一些的。那好,在这种新的加设计架构的这种这种基础之上呢。如果想充分的利用这一点。那么就要求你的编译器compilr。要求你的编译器。

把你的原码编译完的这个指令之后呢。可能进行指令的一个重新排序。重新排顺序。呃,原来是A等于3,B等于4,你代码里是这么写的。但是由于这两个呢,如不如果说他们两个之间啊,后面又把B的值负为5了啊。那么。

边际呢可以对它进行一个一个重新的排序,有可能把B等于三排B等于4排前面啊,马上后面B等于5跟上,后面写A等于3。这件事情很正常。这是一个逻辑上的概念。那么细节上的就是那个汇编语言上的它的一个重排序。

这个。mod了掉还有一个作用呢,就叫做禁止指令的重新排序。那么禁止指令重新排序。它会起什么样作用呢?我通常给大家举例子,举的是这个例子叫做double check lock。

这个例子呢也是非常深入的一个内容啊。好,下面我来聊这个指令重排序的问题。这能空白序其实经常举的就是这个例子。而且这个例子呢原来是一个面试题啊,甚至其实在这个业界里头也曾经出现过很长时间的争论。

就是说我到底应不应该加vololatile。那么这个到底是什么意思呢?没有没有听过性格也没有关系啊,我来一步一步讲给大家听。然,我们来聊呢,到底呃什么是单利?单利的意思呢就是这个意思。

我保证你在JVM的内存里头永远只有某一个类的一个实例。其实这个也很容易理解。在我们工程之中呢,有一些类啊,他真的没有必要拗好多个对象。你你比如说什么样的类呢?权限管理者。权限管理者。

那哥们儿就是专门管权限的,哪个操作呢,我都进行一个权限,我我真的没有必要拧好多个,一个就可以。呃。守大门的对吧?一个就够了。这时候呢叫做单机上的这种单利模式嗯。但这种模式呢最简单的写法是这种写法。

这种写法呢叫恶汉式。恶汉式的写法是说看这里。我有这么一个累。定义了这个类的一个对象。然后这个对象呢是在这个类内部的。同时呢我把。这个类的构造方法设成什么设成private。

那意思就是说你比人说你没法扭我,你不要去扭我。你不要去给我拗manage01,只有我自己能拗,所以我自己就拗了一个扔在这儿。既然别人拗不了,只有我自己能拗,我拗完了之后扔在这儿。那么理论上来说。

我就只有这一个实例了。那什么怎么样才能访问我这个实例啊?通过一个方法叫get essence。我就拿到这实力,给它返回去返回去。所以无论你调用多少次的get instance,本质上它只有这一个对象。

而,这第一个小程序非常的简单,我解释的比较快。没问题,同学给老师扣1啊,有问题直接提。我。嗯。但是这种写法呢非常的简洁,也很容易理解,而且呢由JVM来保证,永远只有这一个实力。

为什么JVM能保证这个很简单,一个class漏到内存之后,这个static是由JVM来帮我们做初始化的。由JVM来帮我们做初始官啊。那那个只有初始化完了之后,你才能使用。这个JVM就直接给你保证。

肯定就只有这一个实例了。那好。但是有的人呢他会吹毛求疵,他会说。我还没开始用这个对象呢。然后我没没用这个对象调这个方法是吧?你干嘛把它给初始化了?你能不能够说什么时候我开始用的时候。

有时候get instance什么时候我调这方法的时候,你再给我做初始化。所以呢。这个是另外一种磁带和样上一种一样的写法就不说了啊。好,所以呢就会产生这种懒焊式的懒汗式的意思是说。

我get instance,什么时候我一开始调用这个get instance的时候。我才给对他进行初始化。当然你这个初始化的话,你尽量不要初始化两次,你应该只能初始化一次才对,不然就成了俩对象了嘛。

所以上来之后,你先判断instance等于空的话,我才初始化。那你可以想象一下,如果有人访问啊,发现它是空吗?我就初始化了。那么后面一个人再来的时候,发现他是空吗?已经不是空了。

那就把这个insense给返回回去。不过。更加吹而求疵的事情就来了,说我不单单的要求你,我用的时候才初始化,我还要求你现成安全。那这里就就要问大家了,同学们,这种写法是会使现成安全的吗?

能不能支持现成的安全性?不会,这个肯定不会嘛。你第一个县程判断它是空,第二个线程同时也判断它是空。第一个线程扭了一下,第二个线程又扭了一下。

啊,这个。所以。你多个县城开始访问的时候,那它一定会出问题,这个我不运行了,就个它一定会出问题,你自己去实验。

所以他会怎么做呢?我们要加一个schronize来解决,这是肯定的对吧?我们加把锁嘛,所以我加这个叫做publicity synchronize to get instance啊。

这句话一旦加上肯定没问题了。那。所这句话一旦加上肯定就没有问题了。

因为这里面从头到尾的就只有一个线程运行。那第一个第一个线程发现他那个空给他扭了。第二个线程。

它无论怎么访问,这个值已经永远都不可能为空了,所以它只能是拿原来第一个县程初始化的这个部分,这是没问题的。但是有的人又开始吹毛求疵,说,你对sronize一下加在方法上,你锁定这个代码这个代码区啊。

实在太长了,说不定里边还有其他业务逻辑。咱们说对于加锁这件事情来说叫做代码能能能锁的少的,就要尽量的锁的少。这个后面我还会提这个问题。所以呢有的人就开始进一步的吹毛求疵。

它会变成新的写法。这个写法是什么呢?上来之后,您先判断,你先别加锁,你先判断判断它为空,然后再加锁初始化。

细力度的更细力度的一个锁,这叫做所细化。也是锁的一个优化的一步。

不过很不幸的是,这种写法是不对的。为什么这种写法不对,我们来分析一下。第一个县程判断它为空,然后还没有进行下面的执行的过程。第二个县程也来了,也判断它为空。那好。

那么第一个线程呢就开始schronized。schronet上来之后,对它进行了初始化,初始化完了之后把锁释放了。但是这个时候第二个线程记住第二个线程也已经执行完这句话了。

它还仍然视为空的那会儿还第二个线能拿拿到这把锁又初始化了一遍。这种写法是有问题的。所以就会产生了好今天我们要讲的vololatile这个问题,这个问题呢是是是是这样来产生的啊,这样这样来问。

我们把这窝老汤给住着了。O看这里。呃,这叫做双重双重检查所,或者叫双重检查的单例。是怎么写的是这么写的,就是if instance等空schronize synchronize完了之后再判断一遍。

这叫做双重检查,它是不是等于空。如果在这种情况下,刚才说的那种现成的问题就不会再有了。来分析一下。第二线程来了。说哎okK你确实是空值,然后呢它进行下面的初始化过程。

假设第一个线程把这个instance已经初始化了。好,第二个线程检查第一个线程检查一等空的时候,第二个线程也检查它为空。所以第二第二个线程在这句话之后停住了,暂停。暂停之后呢。

第一个线程已经把它初始化完了,释放锁。第二个线程继续往下运行,继续往下运行的时候,他会尝试拿这把锁,他能拿到这把锁吗?可以。第一线程已经释放了,对不对?他释放完之后,拿到诊疗所之后。

注意他还会进行一次检查。由于第一个县程已经把ins森初始化了,所以它这个检查已经通不过了,所以它不会再重新谬一遍。因此,这个双重检查这件事儿是能够保证现程安全的。讲到这里。有没有同学有疑问的。

没问题给老师扣1。我马上讲volattile。那说那外面的判断没必要啊,外面判断可以省很多很多的。你不用加锁,外面这个判断不用加锁,你理解吗?不加锁的话,上来不用加锁,你的效率就会高。啊。

刚才我可我没看清楚是哪位同学提的这个问题。我再说一遍,你想你县城,如果你如如果你没有外面这个,你上来之后呢,你直接就开始申请锁,这个效率当然就会低锁竞争了。但是呢呃如果你上来之后先检查。

你是不用申请锁的。你先检查一下多数的情况下,这个值已经不为空了,肯定有个现成吧已经把它初始化了。如果它已经不为空了,那你就直接拿就行了,就跟跟锁就没有任何关系了。呃,听懂这意思了吧。

所以外面这个还是有必要的嗯。好,现在的问题是你看啊,我用了双重检查之后,我起了100个线程,这100个线程每一个能调用一个ge instance打印它的hash code。为了县城之间的互相之间会干扰。

所以我还中间让他睡了一个毫秒。

跑一下。那么结果你会发现呢,我告诉你,就这个程序,无论你运行多少遍啊。

你就算在高并发的情况下运行,拿100台机器同时访问着一台机上的这个geide instance。然后那个每个机器上跑跑个1万个线程,使劲跑。

O。使劲儿使劲儿的跑这个程序,最后运行出来的结果一般也是正确的。嗯。这怎么说,没有外面,一开始方法上不就一样的吗?不是这是两回事。我我际上省略了这其中的一些业务逻辑的处理。

在这种地方很可能有一些业务逻辑。能理解吧,我省略了这些了啊。所以还是不一样的。你加Cle呢的加代方法上的话,那整个的就包括业务逻辑全锁了,没有这个必要嘛。嗯。好。那有同同学会说。

那到底要不要加vollatail好,这是一道面试题。这道面试题他会直接这么问,你听说过单利模式吗?你肯定得说听说过,你要是没听说过单利,你还聊个肾呢。啊,那单立模式里头有一种叫双重检查的,你了不了解?

好,你这时候要说不了解,咱就咱就挂了,就别聊了。你说了解OK那了解的话,问你一句,这个单例要不要加volatile。通过我们的实验来看,你哪怕就是进行压力测试,压个1110万遍,它依然。不会出问题。

你拿到的依然是同一个对象,但是要不要加voltail呢?答案呢是药价,这个以前啊由于这个实验你很难做出来,就是让它出错的情况。所以以前很多人就不加这volat跳,但是它也不会出问题。

那么加了不加多的条问题会出在哪儿呢?就会出现在指令重排序上。好,认真听。这个模型呢特别的复杂,你认真听我们说第一个线程第一个线程。需要你了解这句话,就是instance等于new manager。

那么利用manage经过了我们的。JVM虚拟机的呃编译编呃,sorry这个编译器编译完之后呢,它这个指令呢其实是分成三步。一你有一个对象的时候分成三步,这个指令分成三步。第一步呢是给这个对象申请内存。

第二步是给这个对象的成员变量。初始化。第三步是把这块内存的内容。复制给这个instance,所以它是一。235。好,我再说一遍,申请内存。申请完内存之后呢。呃,这个值啊是一个默认值。

还是给大家在PPT上画一下。

先说 new对象的这个过程啊。简单给大家画一下。好。没有对象的这个过程啊。应对现这个过程呢分成三步啊,第一步呢是申请这块内存。假如它里边有个值的话,呃,I这个值它会给这个I它会A这个值吧。

A这个值它会给这个值呢付一个初始值默认值。这个默认值如果它是in特类型的话,它是一个0O是一个0。然后呢,进行第二步。第二步呢是把这里面成现面料这个值呢设成真真正正的那个初始值。

比如我们给AA付的初始值是8,那么再把这个A变成8。哎,然后呢是第三步,第三步是什么呢?是把这个变量啊,这时候它的值已经是8了,是吧这个变量呢呃真真正正的赋值给我们那个inst。

大家知道那个inst呢是在那个呃站内存里。是吧让他呢哎只想。这个变量的地址。理理解这个过程啊。第一步申请内存,第二步改值。第三步呢把这个值赋值给他。但是如果说认真听。

如果说这里面有指令重排序会发生什么呢?会发生A等于0之后。还没有对AD行初始化之后。好。我们就已经把这个instant的值赋值给他了,也就是说把第三步和第二步给换了个位置。这个A等于零的时候。

我们这个instance里面就有值了,就是已经指向这个这个这块内存了,反正这块内存的地址是不会变的。好,刚才讲的这个内容有没有同学有问题的,你给老师提出来,没问题给老师扣1。也就是说什么呢?

这一个对象在半初始化,初始化到一半的时候就已经赋值给这个变量了。那如果复值给这个变量之后,你仔细分析一下。第一个线程, synchronized的。虽然说它加了锁了。Synchronized。啊。

加了锁了,但是在加锁执行到没这个对象扭到一半的时候,扭了一半,A的就变成0。第二个选程来了。第二个选程,你刚才咱们刚才也多定代码了。第二个线程来了之后,它上来先判断这个instance是不是等于空。

可是大家注意。由于它已经初始化一半儿,而且这个instense里面有值了,它已经不再是空值了。同学们。所以。它不再是空值了。就相当于第二个县城已经拿到这个对象,可以直接使用。

既然拿到这个对象可以直接使用了,我很可能会使用里边这个值,这个很正常。但是呢我本来期望这个值应该是个8,可是很不幸的是呢,这个值是个零。假如在一种超高超高并发的状态,这种情况是有可能产生的。

超白超高并发的状态。阿里京东。秒杀的时候是有可能产生的。如果你秒杀的时候,这里记得是一个库存的值。原来或者订单的值吧,订单的值原来这个订单呢下到1万了1万个订单了。你本来这个值再来一次的时候。

应该是1001。但是很不幸的是呢,中间你读到了一个零的状态。结果这个订单值变成一了。O。不知道我说清楚这个问题没有?所以在这种状态上,你就会出问题。reedemption你说的这个你的这个疑问呢跟。

办初始化没有任何鸟关系。没出始换会完全释放锁,这跟释放锁不释放锁没有任何关系。我说的是这个instance的值已经有了。既然有这个值了,那么你在另外一个县城里头上来先去检查,你会发现这个值已经有了。

你根本就不会进入锁那部分的代码。听懂这意思了吧。那好,那么加了vol会怎么样呢?加了多了跳。指令重排序就不允许存在了。对这个对象上的指令重排序不允许存在。所以在这个时候。

一定是保证你初始化完了之后才会复制给你这个变量。okK这是vololattail的含义,两个含义我就讲完了。看看有没有同学对这块有疑问的。它有两个含义,第一,保证现成可见性底层的实现。

CPU的缓存一致性协议。第二个行业禁止指令重开序。单立的时候,超高低频盘你才可能会出现。但是平常我们写程绩是测不出来的。我是没办法测出来的。如果你要是愿意的话,你可以测一下试试啊。呃,其实是可以测啊。

我跟你说,其实是可以测,只不过重新写下来比较麻烦,怎么测呢?大家知道那个ASM呢是直接。就是ASM是可以直接操作二进制码的。你只要在二进制码呃,这三条指令之间啊,就是说申请内存初始化复值。

这三条指令之间你你你你插插入一些代码睡觉就能测出来。那这个太费劲了,我就懒测了。そ。嗯,好的,我们我们看看同学们还有什么有有没有什么问题。但是有同学可能很难理解说那个中间居然是三条指令。

你你你怎么证明是三条指令啊?嗯我给你看看证明一下,好吧。随便写一个小程序。找个比较简单的小程序啊。嗯。😊,没有了。Just test。面包款啊什么都不写,就直接写 new object。写。

OjectO等于 new objectject。嗯,跑一下。跑掉之后呢,vio这是我后面讲虚拟机的时候一个小工具。这种容易的会观察我们这背方法呢生成的哪些个。二进制码它的code。

它的汇编指令是怎么生成?你看这个汇编指令,这汇编指令呢,它是你要这个对象的时候,有这么几条指令。第一个是newnew就是申请内存。先把内存申请上diplication是复制的就不说了。

new完了之后的第二条指令。dplication这个是下面这指令要用的啊,你不用去不用去管它。第二这个一一条指令你new完了之后申请完内存,申请完内存之后。

invoke special invoke special。你看它调的是什么呢?调的是object initial方法调的是object的构造方法,所以它要用new完了之后调构造方法进行初始化。

初始化完了之后acestore一才会真真正正的把这个值赋值给。欧这个对象。所以你仔细如果看的话,这还不是一条指令的,这是4条指令。Yeah。我。所以这些指令中间是有可能被打断或者重新排序的。

系列 4:P43:【多线程与高并发】Volatile不能保证原子性 - 马士兵北京中心 - BV1VP411i7E4

Oh。嗯。okK好了,同学们我们继续上课啊,看这里嗯嗯。嗯,那么word tell呢刚才我们说了,它能够保证现成可见性,也能够保也能够呃禁止指令重排序。呃,微上呢它并不能够保证原子性。

lo条是不能够替代 synchronize的,这个千万要注意。那么什么意思呢?我们来看这个小程序啊,小程序也比较好玩儿。what cell in the count等于0。接下来有一个方法。

MM呢循环了1万次,让com加加。那么com值呢就会变成9999啊。好,看这里。会变成1万啊嗯。6T呃,我做了一个现程。作为一个list似的list似里面全是现场。聊后取了10个线程。

I等于0I小于是I等于2,然后stres点艾。这个现程里面调用了M方法。10个县城每个县城都调M方法,那一共加了10万次,对吧?

把所有的线程都启动。等所有现程结束。最后输出这个值。嗯,同学们考虑一下。由于我加了窝了条了,每个县城在访这个值的时候呢,一定能是能读到最新的值的。来能不能告诉我最后这个值是多少?

有没有什么问题,会不会是10万?我要不加波了条,大家想想肯定有问题嘛。

你先说不加波了跳。

不加窝了条78000。

好,我们家乐嘉乐宝乐条。

家乐格乐条,你想一下,哎,这个时候是我的新的值一旦改变啊,我的另外一个现生是马上能看见的。另外现生马上能看见,他就应该拿新的值啊,拿新的值来加了,对吧?他正常应该是10万呢。800。

再跑一遍。65000。又跑远。做晚身。反正总而言之是到不了10万的。原因是什么呢?分析一下。原因其实很简单,虽然说你count的加加这块呢。你是保证这个count值改了之后啊,能够。被别的县乘客看点。

但是看光看点没用。呃,现在这count的值是0,第一个线程确实它是一它加了一下啊,变成一了,他把这一写回去了。然后第二个线程也读到这个一了,第三个线程也读到这个一了。所以第二个线程拿到的还是乙。

第三个线程拿到的还是乙能理解吧。所以第二个性能加完是2,第三个性能加完也是2,两个写回来呢,最后还是2,不就少加了一次吗?

所以归根结底是说这count呢count这个值是保证了可见性,但是countt加加本身。它并不是原子性的一个操作。那有同学会说,老师countt加加,这不是一句话吗?它为什么不是原子性?刚才你看到了。

你没有object还是一句话呢?在java的内幕会分成好多条指令来执行。countt加加也是。

这个我在后面。讲虚拟机的时候才会讲到这个指令的问题啊。客看加佳呢本身它会分成好几条指令,至少三条。

所以中间被打断的可能性也非常大。因此,loc了条是只能说。

呃,保证现成的可见性,但是呢它并不能够是替代 synchronized的但保证不了原子性。这句话能不能理解?

系列 4:P44:【多线程与高并发】synchronized优化 - 马士兵北京中心 - BV1VP411i7E4

啊,我就就是就是现成这块内容啊就特别好玩。你如果按照逻辑来讲的话呢,它是这么一个顺序,1234567是吧?77的内容。但是你如果按照优化来讲呢,它这些优化的内容呢可能分布在不同的里面的。

不同的这这个这个步骤之上。所以优化呢我我讲到某一个问题的时候,讲到优化我们就谈一次,讲到优化我们谈一次,好吧,这优化呢所优化这个问题呢,其中有一个就是把锁力度加变细啊,还有一个叫把锁力度变粗。

却说都是一回事儿,什么意思呢?作为Cpro宅子来说,你这个锁呢要。这种不是很很剧烈的前提之下,你这个锁呢力度最好是要稍微小一些。好,我这个小程序呢叫fine course, fine是细化的。

co是粗糙的这个意思啊,fine course look什么意思?看这里。

呃,如果说我们这个M方法啊,它假如说前面有一个有有一堆业务逻辑,后面有一堆业务逻辑。

这业务逻辑呢我用sleep来模拟了它,然后中间是你需要加锁的代码。那么这个时候你不应该把这个锁加在整个方法上,而应该加在哪儿呢?只加在。

靠在加加上。听懂我能理解的意思吧,这非常简单。

这叫做呢锁的细化。那有的时候会不会进行锁的粗化呀,有有有没有有没有?没有了。你们能想象一种情形,让你对进行所优化的时候。不是细化,而是让它变大变粗。有这种可能性吗?能想象吗?考虑一下。

争的特别频繁的时候,没错,假如你这个锁,由于你锁的力度呢越编越细啊,特别特别。越变越细哎。好,越不用心好多好多小的细索啊,就跑跑在你这个上面。

这个这个这个这个方法某或者说某一段业务逻辑里头好多好多特别细碎的锁。那你还不如干脆给它弄成一张大锁,它的征用反而就没那么频繁了。嗯,也会容易容易死索是你写程序的问题。你程序写的好也不会发生4索。

我说的优化呢是是说你程序没问题。但是你可以有进一步的更好的写法,这个叫优化。这个时候呢你可以某些情况是可以进行锁的粗化的,把锁加大。这是没问题的。数据库的一张表。你在某一行所有的行上都加锁。大哥。

我跟你说,你的效率就会累死。随便的读写,某一行上都加锁,那你不如把整张表都加不加拉锁得了。嗯,这个所粗化所细化的问题呢,是一个概念上的东西,它并没有一定之规,理解这个概念就可以了啊。好,关于这个小问题。

我们过了没问题吧,有问题的老师扣一啊,sorry有问题扣2,没问题扣1。我们以后没问题,永远扣1啊。H。那好,下面又是一个小概念,很简单,很直接就能理解。所以我速度会比较快,你认真听。锁定某个对象O。

如果O的属性发生改变,不影响所的使用,但是O变成一个对象一定会。产生产生问题。什么意思?objectO等于6object。如果我们把它中所 synchronized的O。

但是你在某一种特定的不小心的条件下,你把O变成了别的对象了。大哥。这个时候现成的并发就会出问题。这事儿太简单了,因为我们刚才说过。这个对所呢是在对象上头上的两位来代表的。

你这个县城本来大家伙都去访问这两位了。结果突然之间,您老人家把这把锁根儿变成了一别的对象,去访问别对象那两位了,这俩之间还有关系吗?俩现生。没有任何鸟关系。因此,你如果用对象做锁的时候。怎么写?

同学们来告诉我怎么写。😊,不让它发生改变。Okay。所以你会看到别人的那些大牛的人写的程序啊,它非常非常的规范和细化。这个final它是少不了的嗯。啊,很简单啊,没问题吧,有问题提没没问题扣1啊,继续。

😊,sring这个类型嗯,我我已经讲过了,不要用s stringring类型来作为锁。

系列 4:P5:【JVM调优实战】什么是垃圾?如何定位垃圾? - 马士兵北京中心 - BV1VP411i7E4

佢这里。来聊聊JVM的DC的历史啊,就这块的内容呢,我稍微补一点最基本的这种技术上的概念。我们先来说呢,到底什么是一个垃圾。就是我们刚才说嘛,如果是你呃采用这种引进垃圾回收器的这样的一些个语言的话。

那你你总得找出来,就是业务线程在这里不停的扔线头,扔线头,扔线头,线头和线团之间呢,有各种各样的线来进行关联。好,作为垃圾回收线程的角度来说,我得去定位啊,这这这到这到底哪个是垃圾,哪个线头是垃圾啊。

怎么找啊,这里面的找法呢,一共有两种。这什么是垃圾?我们先定义什么是垃圾?这垃圾呢其实很简单,就是你看这你看下面这个对象,这个对象呢在运行的过程之中没有任何引用指向它了。

原来呢有一个成员边论的引用指向它。有现在没有了。好,这哥们就是垃圾,这肯定的。😊,没有人没有引用指向他了。好,他就是垃圾。但是我们怎么定位这个垃圾呢?定位这个垃圾的话有两种方式。

第一种呢叫reference count图。你看一下看一下动画就理解。就是这个对象呢,我给他做一个计数,引用计数法,这叫。有3个目前有三个引用指向,我我脑袋脑门上写了一3啊。接下来如果有一个引用消失了。

变成二,有一些用消失变成一,有一个引用消失变成0。当它变成零的时候,这哥们儿成为垃圾。python就是使用这样的方式。这个叫引用基数法,引用基数法有毛病,毛病在于哪儿呢?我们假如说有一堆垃圾。

有三个垃圾。A对向BB对向C。C又指向A。好,所有的对象都有引用指向,但是没有任何其他的引用指向。这三个对象中的任何一个啊,这叫做三个垃圾,一堆垃圾,一坨垃圾。那么像这样的话。

如果你用reference count的方式就找不出来。因此,java里面采用的并不是这种方式,怎么定位一个垃圾。java里面采用的是这种方式叫做。根可达算法叫reearing。这算法一说,你就明白。

根可达算法的意思是我们从根上开始,什么叫根?媚函数里面,你简单理解媚函数里面的一个一个变量,这就是根,就魅函数。通过这根线来跟着捋捋到谁,谁就不是垃圾,它的成员变量又指向了它,它的成员变量又指向它。

又指向它又指向它。好,这几个全部是垃圾。顺着这根线找找不到谁的时候,竖的搜索算法,找不到的这些全是垃圾。这个大家能听明白吗?有没有同学有疑问的?嗯,循环引用不能把引用断开吗?人家业务逻辑就要循环引用。

你为什么要给人断开?你断开,人家业务逻辑不变了吗?大哥。当然大厂面试的时候呢,有一个问题叫做什么是根儿啊。如果要讲这些细节的话,我我倾向于讲东西呢,是先从很高的层面来讲。呃。

我建议大家学东学学课程也是一定是要什么呢?先建立知识体系,这件事情超级重要。有很多人呢连最基本的学习方法都不会可以说啊,从小学到大学学了这么多年,最基本的学习方法没学会。一定要先建立知识体系。

然后再去查漏补缺。我讲的再形象一点,你掌握一棵知识树的时候,先把树干给我掌握了。然后再去两个树枝。然后再去。掌握树叶。你的树干跟树枝子你啊你的树干只要是特别稳固的话,你树叶想刮多少刮多少。

现在很多的碎片化的学习都是让你掌握树叶的知识。你掌握了多少树叶都没有用,因为你没有建立整个树干的体系。了解一个庐山,你得坐着飞机从上空飞过看庐山的整个面貌。

而不是说你到庐山脚下某一棵树底下去研究庐山的蚂蚁窝。这种纯属扯淡。听我说。我上这么多年学,我记得我上大学的时候有一个学期把。清华图书馆所有的物理书。那藏书很多的啊,大概得有。

几万本1一个学期我全把它全部它看完了。当然没记得多少,但是整个物理的体系慢慢就建立起来了。😊,呃,小伙伴们,你们呢如果不同意这个说法的话,我不管你同意不同意,你采用一下,你试试看就知道。

要先要先建立知识体系。听懂了吗?嗯,建立知识体系之后再去研究那些细节。好吧,知识体系的建立呢就是囫囵吞枣四个字叫囫囵吞枣。有好多人学东西啊特别好玩。呃,他在学习的过程中,假如说这是一棵知识树。嗯。

他在学习的过程中,他学到某一个节点的时候,他会顺着啊就每一个细节。比如说别人给他讲dos窗口,你怎么设置环境变量啊,咱们学只要的人一般都会遇上是吧?

怎么设置环境变量怎么设置passclass pass他就开始研究哇这dos挺好玩的啊,这dos还能写BAT这这个这个这个点这这呃脚本语言呢啊,我研究研究这个脚本语言怎么玩吧。

然后啊这dos窗口怎么产生的呢?研究研显卡嗯。😊,杨岩先生,哎呦,哎,玩玩PS哈哈我跟你说,完蛋,你要这么学,你的时间就是全部浪费,没有用。😊,而是你应该怎么学呢?先二话不说,把整个这些关键的点全拿下。

拿下之后呢,再去发散,再去纠细节。我大概就是这意思,好吧。嗯,那就是先先看完本书呗。行行行,你这个理解能力我也是醉了,看来我还是我表达的不够啊,sorry。好,我讲到这儿呢。

我是希望大家呢先把这个什么是根儿这件事呢先略过,不要着急。因为如果作为。呃,官方的非常规范的定义来说,你得去看哪本书呢?叫JVMS。

The Java virtual machine specification。呃,这本书呢是在orac克网站上可以下载,它的全称叫做JVM的虚拟机规范规范大哥。他很枯燥的。

也只有像老师这样特别无聊的人才会去读他。其他人你不用读。作为哥来说。这本书上给你说的非常明确,它包括这么几部分内容,GYM stack的内容,tack站native method stack又是站。

runtime constant pool运行时常量常量迟。steady reference method area方法区里面的静态引用,以及我们的class类的对象。这里面的任何一个拿出来。

你不了解JVM底层,直接就把你给看晕了。所以你不用管根儿嘛,我给你举个最简单例子就行了嘛。ma方法里面呢有一句话叫object小O,等于new objectject。好,这哥们就是根儿,听懂了吗?

很简单,就是方法整个程序开始执行的地方,最先建立起来那些对象,这些哥们们叫根儿叫root。呃,专业说它就是这Mmt里面内容。Stack吗?站里面的我们的方法里面不是位于我们线程站吗?主线程站对不对?

站里面对象。get了吗?好,我们可以继续吗?先把它略过好不好嗯。😊,所以从根儿上开始找,本意就是从根上开始找,反正是顺着根儿捋捋捋嗯。就是我我还是喜欢讲的稍微形象一点啊,形象一点就是你比方说你。😊,嗯。

你女朋友你男朋友啊,你你你们哥仨,你们姐仨啊,甭管是哥仨姐仨。在一个空间里面,内存里面扔小线团儿。谁是根啊,你们仨就是根儿,你们的手捋着这个小线头,捋到的全都不是垃圾,凡是捋不到的。

中间那个线给断了的全都是垃圾。就这意思。这样的话呢,你就不会给产,就是那种原来像这种互相引用的。但是哎你顺着歌,只要找不着,他这哥俩就是垃圾。够啦。好。这是第二种算法,叫根可达。非常简单啊。

系列 4:P6:【JVM调优实战】常用垃圾回收算法与常用垃圾回收器 - 马士兵北京中心 - BV1VP411i7E4

当我们知道了什么是垃圾。当我们定位了什么是垃圾,定位好了之后呢,我们要把它给清掉,对不对?好,清除算法从上个世纪60年代开始发明的,到现在为止。几十年过去了。就这三种清除算法就这三种。这三种是啥呢?

第一种叫mark sweep,第二种叫copy,第三种叫mark compact。背窝就行了,特别简单。仔细看。第一种叫mark sweep,就是我找到了标记,标把它标记成为垃圾之后把它给清掉。

就这么点。原来O这哥们是垃圾了,怎么办?打上个标记,说这块空间可用了,可以可以使用了。😊,后面的人可以在这里面分配内存了。😊,搞掂。梦洁说,什么情况根不可达,没想出来。我的老天爷呀,梦洁。

你是玩语言的吗?object O等于 newobject。好,这里有我小O指向,它我写O等于空。来,你告诉我这个O指向谁,这个引用还有没有?Yeah。哎呀。😔,Yeah。让我忍住怒火继续给你们往下讲。

开个玩笑啊嗯。总是有两年年得睡呀。😊,看一下看一下啊,我们回回着气氛,听课听着怪累的,稍微聊会儿小天天ok。😊,好,我们来看这个标记清除啊,标记清除的意思就是哎我们简单说吧,我们顺着根开始找。

找到的全都不是垃圾,这些找不着的,全是垃圾,怎么办?把它们清掉。哎,这就叫标记清除。简单吧,就这么简单嗯。找到的这些全都不是垃圾,没找到这些全是垃圾,怎么办?清掉咔嚓咔嚓清掉。好,标记清楚。

比较清除这种算法呃,虽然说比较简单,但是有它的毛病,毛病在哪儿呢?当我们好多好多次运行运行很长时间之后,你会发现这儿也有青掉的部分,这儿也有青掉的部分,这儿也有青调的部分,这儿也有青掉的部分。

你会发现你的内存。变成了碎片化特别严重。碎片有好多有好多洞。然后这时候你要是想来了一块大的空间,我想分配下去,你发现你找不着了啊,碎片化特别严重。嗯。好嘞。当然呃第二种算法没有碎片化。但是也有它的毛病。

第二种思环叫拷贝,拷贝也特别简单啊,认真看。其实啊就很简单,不管你们家多大。😊,你们仨只能用一半儿。你女朋友,你男朋友好,在里边玩吧,随便玩随便折腾。折腾完了之后呢,我的垃圾回收器进来了啊。

你妈妈拎着一把笤帚就进来了,他进来之后干了一件什么事儿呢?顺着你们仨开始。😊,这根儿开始找找找找找出来的东西,整体性的全都复制到另外一半里面去。复制过来,同时排列好,看到了?原来那个没排列好的哎。

都给它排列好,然后把左边这半边整体性的全部回手。OK这个算法也简单,效率越高。但是我相信你那大腿想一想,也应该知道他的毛病之所在。还用我说吗?浪费内存。没问题吧,很简单啊嗯。😊。

我们再聊第三种叫mer compact。mark compact什么意思啊?这就更简单了。就是既然第一种呢碎片,第二种呢浪费内存,干脆呢我就在回收的时候直接把它整理好。什么意思?再说一下你你女朋友。

你男朋友好,扔小线团。然后运行的过程之中呢,产生了各种各样的垃圾。当我在。回收它的时候,我顺带着把内存整理一下,整理成什么样的?整理成排列的整整齐齐的,排排坐吃果锅,你们仨在这儿后面的有用的。

在后面跟着。好,剩余所有的空间都是可以用的。very good,这叫标记整理,叫标记压缩。这种算法。呃,也很形象,就是你的你的硬盘的碎片给整理嘛。😊,他也没有这种内存的碎片化,它都是连续的空间。

但是问题就出在效率很低啊,它是这三种之中效率最低的。好,一共就有就这三种。从上个世纪60年代开始到今天。我告诉你,就这三种,没有别的。不知道我说清楚没有。这块有疑问吗?是。很简单吧。听我说。所以呢。

看这里啊。就这三种算法呀。好。是。我的中文呢中文。就这三种算法都有毛病。都有毛病。就是说你要是把你的内存当成一整块的时候,无论你采用什么样的算法,都有它自己的问题。所以。垃圾回收剂非常聪明。

它呢是用这三种算法综合运用,然后同时对内存进行了划分。产生了各种各样的不同的形成自己个性的垃圾回收器啊,妈妈爸爸、爷爷奶奶、叔叔阿姨都可以帮你来进行垃圾回收,但是每种都有它自己的特点。啊,同学们。

下面我们看垃圾回收剂总的图。垃圾回收剂的总图。嗯。喂大家放在这儿啊。好,那这是垃圾回收据的总图。那么大家听我讲啊,这垃圾回收据总图呢在JVM从JDK1。0诞生。到现在,JDK14。从1。0到14。

一共诞生了10种垃圾回收器。这十0种垃圾回收器我一会儿呢沿着历史,我慢慢给你捋出来,你就理解了这10种垃圾回收器它到底是怎么玩的了。每一种的特点是什么?好,我们先来把它背过。有同学说老师。

你这个东西要背过吗?没错,你跟面试官想吹牛逼,或者你想把它掉下来打的时候。😊,你就把它给背过,但是他也不难。这几种垃圾回收器呢。你我你先花个几十秒先大概看一眼。分成什么呢?分成是把内存分成两部分的。

以及把内存分成多部分的。嗯。好,看这里前面这6种是属于内存分带模型,后面这三种呢属于内存不分带。但是G one呢它逻径上是分带的abilent是个特别好玩的垃圾回收器。

叫做它是它是什么都不干的垃圾回收器。好,听我讲,我一个一个啊,今天是已经9点20了。没关系,我一个一个的给你们捋清楚,好吧。不。好,大家看这里啊。呃。我们先说啊,就是这个垃圾回收器的演演化过程。

这个垃圾回收器的演化呢。Yeah。GC的演化这个垃圾回收器的演化呀是随着内存大小的。不断增长。耳眼镜。这句话很重要,就是为什么有那种比较简单的垃圾回收器,它不用后面越来越复杂,各种算法也越来越复杂。

为什么呢?原因是什么?就是因为内存的大小在不。

系列 4:P7:【JVM调优实战】垃圾回收器Serial与Parallel - 马士兵北京中心 - BV1VP411i7E4

最开始最简单的垃圾回收算法呢叫做cereal,就是这种cereal。当然,cal有两个,一个叫cal,一个叫ceal old。有同学会说了,老师它为什么分成俩,原因是。

为了因为你你要把一整块内存用统一一个算法来算的话,怎么算都有毛病。为了综合运用。最开始的时候啊一直到现在为止吧,这地块1。8默认的都是把内存分解成为两个大的年代。看一下。这两个大年代呢分别叫做新生代。

一个叫新生代,一个老年代。我们怎么区分新生代和老年代?这件事特别简单,就是刚刚诞生的对象优先的往新生代分配。有同学可能抬杠说老师那个个特别大的会怎么怎么样。😊,不用抬杠,别着急,那些都是细节。

我们先把最基本的概念先掌握新生代老年代。学东西是要分层次的,先把最高层次的先掌握啊,然后再慢慢去纠哪些细节啊。😊,好,看这里。一个叫新生代,一个老年代,新生代是什么意思呢?老年代是什么意思?

新生代很简单,刚刚诞生的对象,特别年轻的对象,年轻的。刚溜出来往这儿扔。然后有一个是老年代,老年代是什么?经历过一次垃圾回收的,我们任何一个对象说来了一次垃圾回收过程啊,垃圾回收进来了,扫了一遍。

没把你给扫走,说明。你长了一岁,这个对象长一岁,当年龄越长越大,超过一定阈值的时候。它就会升级升级到老年代。这个意思。那为什么涉及新生代?为什么涉及老年代?原因是。

如果一个对象经历好多次垃圾回收都回收不掉,说明他是老顽固。他如果是老玩固儿的话呢,我们就不要每次都扫它了,我们把它扔到老年代去。什么时候内存里装不下了,我们再扫它一遍,把里面的东西全部清掉。啊。

它效率上会会会提升,不用每次都扫它。那么新生代的概念是什么?新生代的概念是一般来说。扫他一遍,这个新生代的时候,很多对象可能就被我给淘汰了,就只有一个活下来。那么就直接把它扔到这个空间。

扔到新生代空间里头,我就频繁的扫它啊,反正扫一次,说不定就把你给情回回收掉了,这是新生代。那么这个时候呢。就可以根据不同的对象的特点,你发现没有?我们根据不同对象特点,就可以采用不同的算法。

我们在新生代里面采用什么算法呢?新生代的算法叫做复制算法叫做copy算法。在老年代里头采用什么算法呢?采用我们的mark sweep,就是把它标记出来清掉,这是一种或者是mark compact。

或者是markwe和mark compact的组合。我前期先进行markwe,后来觉得呃碎片块太严重了,我就对对它进行一次整理等等。所以不同的年代算法不一样。因此在GDK早期的时候啊,一直到现在吧。

JDK1。8都都都支持这种分带算法,分带分带模型。这就是内存的分带模型。但有同学会说啊,我我叫到这大家还能跟上吗?能跟上给老师扣个一来,没问题吧嗯。😊,对对对啊,应该没问题。好呃。

这种分带模型呢到目前为止,这K。8默认的垃圾回收器,它叫做PSPO它依然采用的也是这种分带模型。分带模型直到现在,只要你内存不是个儿不是特别大,它依然运行的还可以。如果说你个儿超级大。

然后需要调优的时候,你这种分带模型它有天然的毛病就已经不行了啊,这个我们后面再说,我们下面来解释,年轻代呢这个拷贝算法,它是怎么拷贝的。我们理解的拷贝算法不就是说我们一分两半儿。

然后这边用完了拷贝到这边来,这边用完了又拷回来等等,不就这样吗?但是并不是。😊,年轻代的拷贝算法是根据工业实践统计出来的结果。一般来说,一次年轻代的回收,我们称之为minorDC或者叫YDC。

一次年轻贷的回收,这个回收它会回收掉90%对象。举个最简单的例子,你一个for循环里边不停的扭扭出来很多对象。除了这个for循环,这里面扭出来对象就没有了。好,就所以你回收掉的话。

一次性可以回收掉大量的对象。😊,根据工业实践的统计,人们发现扔到年轻的对象经过一次垃圾回收被扫掉的可能性90%。如果这样的话,我就没有必要说你想想看啊,我就没有必要分成两半了。

因为你一次剩余的对象就10%,你复制过来就占10%空间。哎,没必要这么浪费空间,占这分成两半,我可以这么来分,它默认的比例叫8比1比1。他是这么这么来复制的,怎么复制呢?一个对象产生的时候。

优先放到伊甸区,伊甸园区人类诞生的地方。10个对象放进来,一次扫描之后扫掉了9个。活着的扔到40万1。虽然它是这个比例是一,但是由于我们活的对象特别少,没关系,它已经能装开了,能撑开了。

然后整体空间全部回收。这是呃。整个的这个这个年年年年轻代回收的这个算法。OK好,那这个算法下一次呢下一次我我又往里头分配了对象了,又分配了10个,又扫掉了9个。那这时候怎么办呢?

你还往svivver一拷贝吗?不是下一次是把这个一定区跟这个svivber一。😊,这哥俩一块扫描。把这个swive一活着的放到另外一个svivver,把一恋区活着的也放到另外一个swivivver。

然后把这个svivver一和一恋区全部右都清掉。当然下一次呢就把这个svivber又拷拷回来。😊,啊,这过程很简单的,不知道我说清楚没有。😊,呃,有没有同学有疑问的呀?DMOU。

说剩余对象拷贝到别的地方,引用地址会跟着改变吗?你你挪了地儿了,你家原来住2号楼308,你挪到你挪到1107了,那引用不不跟着变吗?你不跟着变还能找着你吗?大哥。中文你还用问。没听懂啊,没听懂就算了。

没听懂呢,让自己放松放松。就当个故事,当个卡通听。swi装不下呢,你猜猜看你拿大腿想想,如果s外装不下了,你会往哪儿扔?老年代嘛老年代是最终。承受最终的。好。所有的装不下的东西的地方。不要了,疯了吧。

你。😊,你的业务逻辑不要了是吗?计算计算着突然一堆数据我不要了,太任性了。服。😊,嗯。服你了,好吧,再也不被这事撒尿了。两个surviver是什么关系?大哥,你还没听懂啊。

第一次扫描活着的都扔到这个svivvever,那第二次扫描也不能活着的往这个slivivver扔啊,扔到另外一个嘛,这个svivver就清掉了。下一次呢下一次把这个servvivver活着的又返回来。

把这个关掉。😊,好吧好吧好吧。😔,这么费劲吗?来看看看看看看看动画看动画。我我其实想偷点懒儿,不想给你讲这动画了。没想到你。这么费劲。一个对象产生优先往占空间分配。但是我我们暂时先把这个细节略过,好吧。

先不管。他会往一恋区里去取。如果经过扫描之后,他还活着。svivever一下一次扫描它还活着。svivber2,然后sveber一就清掉了,听懂了吗?然后swiver2里面还有火了。

又回到swiver一,然后svivver2和一点又清掉了。300什么时候年龄够了?老年代搞定了吗?好还有没有谁要疑问的?来,这块没问题的,给老师扣1。什么时候负DC?你问了一个触及灵魂的问题。

每一种不同的垃圾回收算法触及负GC的时间点。和机会点它都不一样。总而言之,言而总之,最简单的说法叫做对象分配不下了。我就要GC。老年代会满吗?你拿大腿想想,不断的由对象往里面升升级升级,升级到老年代。

你说他会满吗?好,他满了之后怎么办呢?他满了之后就会诞生FDCFDC整体回收。所以年轻代的DC经常会发生,什么时候会发生呢?年轻代满了就会产生年轻代DC。什么时候会产生总的DC呢?

全DC负DC老年代满了。就会产生fluor d say呃嗯。淘宝不知道说清楚没有啊,小伙伴们嗯。😊,Good。这里面细节太多了,你看看你还要跟我说,还要跟我聊finalize,还有还要怎么怎么怎么样。

大哥,别这样啊,这样聊起来的话就真的没完。好,看这里。发回来啊,你记住我还是那句话。你永远记得我的学习方法是最重要的。先把这里面所有的大体的内容搞清楚,然后再去钻研细节可以吗?老师有东北味儿。

你咋知道的呢嗯。你是咋知道的呢?Yeah。marGC大哥,你拼错了,叫mar GC。是。嗯哼。😊,数DC不是在永久带吗?我的我的老铁呀,你你先听我讲吧,行吗?

你们就别在这儿混混混了吧唧的这些概念混来混去。什么叫永久带?😡,永久的叫permanentgenium permanentman area。永久带这是永久带的含义,这个是放clance这些原数据用的K。

好,perman area它在1。7之前和1。8之后,这两个是有不同的区别。1。7之前这个东西叫perman area,1。8之后,这个东西叫mat space,叫原原空间。好,这两哥们儿无论他怎么变。

都叫做med area。以前有同学总是把这仨概念混一起,别这样。你既然到我这儿了,我就给你把细节给你揪开。就是你不读java虚拟机规范,这概念你是搞不清的,当然也不用你读,老师读了,讲给你听就行。

抽奖啦。为什么我又没说9点我又没说9点半抽奖。好。下面我继续,我先把整个垃圾回收的故事给你们讲清楚,好不好?没事这样是年轻呆吗?😊,mes area是另外的空间,既不是老年代,也不是年轻代。

它是另外单独的空间。好,我们先把这故事讲清楚,随着内存大小的不断增长而演进,我们大概明白了什么叫做分带算法,对不对?好,在明白了,大概明白了什么叫分带算法之后啊,我们来看看。像这个图先先不不给你们讲了。

这图要讲起来就又没完了啊。好,看这里。你不要想这一节课把所有细节全掌握啊。大哥,我这讲了好几十个小时的课,你非让我一节课讲完,那也不不可能的。😊,好,看这里啊。呃。从呃内存特别小的时候。内存很小啊。

这这Java刚诞生的时候啊,那会儿内存特别小,大概就几兆到几十兆,就就就这么少啊。我记得那会儿8兆8兆内存是吧?呃,几兆到几十兆内存。😊,Shit。好。几兆到几十兆嗯。Yeah。这样一个内存。

这个内存啊它的那个采用的垃圾回收器呢,就叫做cereal。这cereal特别简单,我稍微给你一说,你就明白了。你看这里也给。根据JY messagejava虚拟机规范的定义,seal是什么呢?

叫做esttop the world copy collector which uses single j thread说读一下来叫做esttop worldsto world世界停止这个词呢叫STW。

S T, W。这个很重要,你记住这个词儿以后就说SCW不要跟人说世界停止,或者说什么什么什么什么乱七八糟的,不要不要这么说,就直接说SCW专业,显得你特别专业OK。

copy collector with uses a single G thread使用了一个单线程的GCGC线程。形象一点儿。咸阳鸟是江子弟江子地。你们那哥仨,你你女朋友,你男朋友好。

在里边扔线团扔到一定程度,满了满了怎么办?好,这哥们儿是工作在年轻带的。满了满了咋办?很简单,你妈妈进来了,哪里来着一根扫帚,来了之后的第一件事儿。😊,你们仨给我停。

stop the world业务线程全给我停止停。到我了,你们仨给我停住,不许再动了。😡,不管你什么。😡,什么姿势什什么什么动作,不许再动了,因为我要清理垃圾了。

接下来你妈妈就顺着你们三捋捋捋捋捋捋捋到的这些全都不是垃圾,把那些垃圾全都清清除掉。听完了之后说你们仨继续go on,等你们仨又玩了一段时间,又满了怎么办?你慢妈又进来,停stop。😊,然后。等他清完。

你们仨继续。听懂我的意思了吗?这一个县程。对。这就叫STW叫stop the world进来给我停止,停止之后,垃圾回收去干活。由于他工作在年轻代,所以他叫做拷贝color。使用了单线程。

一个线程就够了。为什么一个线程就够了呀?好。看好。为什么有见人就够了,很简单吗?😊,因为内存少啊。空间特别小。Yeah。Yeah。年轻的也是这样的。老年代。也是这样的,老年贷也是单线程。

等年轻贷回收了很长时间,老年贷转满了产生负D息的时候怎么办?😊,也是单县城,你妈妈又进来了。它这时候老年代的叫做esttro world max compact collect that uses a single d thread依然是单线轴。

只不过他这时候是工作的老年代,in斯达的算法是标记清除或者标记压缩,或者标记清除完了这之后,碎片化过于严重了,怎么办?进行压缩。可以了吗?同学们很简单吧。😊,来可以继续的给老扣一。这就是sal的算法。

ok。所以这张图啊我们翻回头来再看又去哪儿了。你看。我一下就把这哥俩给讲了。好,这是常用的组合。那么下面我觉得我都不用怎么讲,你就明白了,下面叫什么叫parous gal,这句话什么意思呢?

就是当你的内存越来越大了,同学们内存越来越大几十兆到上百兆,甚至到一个G的时候。Yeah。这个没有一定之规啊,就是他跟你的业务是有关联的。什么时候你觉得业务不好玩不好使了。我告诉你。

你这个时候就得考虑所谓的调优第一步换垃圾回收器,这种垃圾回收器不好使了。同学们,你们想想。为什么内存变大,单线程就不好使了?很简单嘛?你原来啊你们家3平米,你妈妈一个人蹭蹭蹭两秒钟就扫过来了。没关系。

停两秒没关系的,很多。这种业务啊暂停2秒钟,卡顿2秒钟没关系的,可以接受。或者几几十个毫秒就扫过来了。没关系啊,可以接受啊,没有问题。所以在这种情况下。你单县程就完全没问题,但是你们家现在变大了。

你们家现在是100个平方,100个平方。你妈妈一个人要清理过来,清理一次性清理100个平方,要清理多长时间?太长了,半小时。妈呀,有没有人能够忍受半小时,你的程序不动。你们现在正在进行双十一秒杀。

用户下单之后,突然间半小时不动,你的服务器没响应,为什么没响应?因为你们哥仨是不是都在那STW都在那蹲墙角呢?😡,听懂了吗?所以。这时候单线程不够不好使了,拿大腿想想优先采用的解决方案是个啥呀?同学们。

多建成吗?漂了。哦,这种叫 parallelel,叫并情。多现场。好,变行多线程工作在年轻代叫做 parallelelcaage,工作在老年代叫paralel old。如果用图来画的话。

就是最开始是你们哥你们你们哥仨在这里工作,突然间。满了满了怎么办?你妈妈,你爸爸,你姥姥,你姥爷一块儿进来。😊,你们仨给我听,然后。他们四个一块干活,迅速的帮你清理掉整个的垃圾。来,你们仨继续。

周而复始。好。这就是zeal和zeal old parallello scavvenge和 parallel old它的玩法。讲错误了吧,哪里。哪里错了,你说出来。🤧。是朋友no。你错了,孙汉南。

parlo gal,parlo old,这哥俩的组合。这是经常用的,简称。PS加PO。强妞我还没讲呢,你着啥急?😊,我告诉你。你你们你们生产环境里头啊,我告诉你1。8,如果你们生产环境用的1。8。

你没有换过任何垃圾回收器的时候,恭喜你,你的默认垃圾回收器就是这哥俩,请你给我记住它,它叫做PS加PO。叫p sc,叫parlo old。哎,有同学可能会说,老师,我怎么知道我用的是哪种垃圾回收器呢?

严格讲,这是明天我要讲的内容。但是今天呢既然你们问到了。就稍微跟你们说两句,可以说两句吗?对这样来说,你只要敲一个指指令就可以heit。什么情况?

。嗯。😊,java杠XX。frame迎 come flag回车,当然带一个带带带一程序或者带一个version吧。好,这里呢它会把呃你加格区拟已经启动的时候,默认的那些个参数全给你列出来。

注意看这里面有个参数是什么?叫做us看了吗?来看一眼。这是你java启动的时候,默认带的参数叫做什么?叫做us parallel。哎,那有同学可能会说,老师这个us parallel到底是个什么东东呢?

放心,像老师这么体贴的难言。肯定给你做了笔记了,是吧?how you parallel是个什么东东呢?你,找着看啊,我找着看我记在哪儿了啊。😊。

Here。这个us parallel d呢指的是okK就是 parallel scavvenge和 parallel old的组合。好了。你可以继续了吗?可以继续,老师扣一了。😊,那这个笔记在哪呢?

明天找丨小丨姐姐拿。我今天稍微给大家调整调整。好,到现在为止,你们听起来应该相相对比较轻松吧,也不太难吧。因为你先建立比较轻松的整体性的树干,我们再去追究那些树叶子。哎那时候你就轻松好多PPT给不不给。好。

我刚才讲了两种组合了,第一种是ceal的组合,第二种是plor的组合。调优的话呢,我明天给大家讲讲这块儿怎么调优。因为JDK1。8,只要你没改过,就是这哥俩,好吧。好,我们继续。随着空间越来越大。

现在不是几十兆到上百兆1G吗?现在空间变得更大了。现在是。1G或者几十兆到什么呢?到。第十记。数十计。好,我告诉你啊,到数十级的时候,你会发现,无论你怎么玩儿。你采用多少个人来啊。

你说我采用我我调一个团的人来来帮我parel嘛,原来原来只有一个,后来我把它变成N个多个四五个,四五个不够使了,我来我来四五百个行不行?我来一万个行不行?这里面就牵扯到一个操作系统的最基本的概念。

就是线程是不是越多,它的效率就越高。是不是线程越多?效率会线性提高,是这样的吗?不一定。明明确说。县城到达某一个预值之后,它的效率反而会降低。Yeah。原因是什么呀?原因又回到了这张图。

刚才我看最开始我讲这张图的时候,老师就就就就就同学们不是说老老有这张图。没错,原因就回到又回到这张图。为什么?因为一颗CPU的核或者一核的CPU同一时刻只能执行一个线程。假如我们有16核。

最多在同一时刻能执行16个线程同时执行。哪怕你使用线程撕裂者啊,最多也就是说四核八线程、8核6线程,总而言之它是有数的。就算是你16个县程。同时在运行。那么你这个时候派了1万个县城过来。

你猜猜看会发生什么会发生排队和切换,什么意思呢?就是。我这1万个县程,我每一个都要让他有执行机会,我怎么办呢?我就执行你一会儿执行他一会儿,执行你一会儿执行他一会儿。在执行你的过程之中,把你拿走。

把它拿进来。😊,好,这个过程叫做线程的切换。线程切换本身也是需要消耗CPU资源的。如果现程数量特别多的时候。上下文的切换context switch,这是它的专业名词。好。

现程切换的所占的资源就超过了县程本身运行。所占的资源。所以CPU会把大量的时间用在线程切换上,它的效率反而会降低。不知道我说清楚没有?一一个厕所只有8个蹲位,最多有8个人往里蹲在里头蹲着。

后来来了8万人,你猜怎么着?怎么办?CPU就把这8万人排好队来把你拎进去。蹲110个毫秒,把你拎出来,换另外一个。注意你们哥几个排队协调这个资源,CPU也得管着,所以CPU会把大量的精力浪费在这个上面。

因此,不是人数越多越好。所以在在你到达一定阈值的时候,到达啊好几十个G的时候,我告诉你你再增加多少个线程,嗯,没有效率提升不上去了,这时候怎么办啊?这时候就诞生了惊天地气鬼神的concurent的玩法?

Concurrently就会中。刚才这声音有点泰俊的味道,太太太你个头啊,说太俊吗?是蛇赛花吗?好,这个叫做concurrent d。我告诉你。垃圾回收器里面有哪些是concurrentDC呢?

here著名的承天启后继往开来,历史清史有名的CMS concurrent mark sweeppe。以及和他配合的朋友。好,继续。Thank。替代CMS的G1。后面的ZDC。后面的悬念咒啊。

这些所有的后面所产生的全都是concurrent。Concurrent。Okay。好,我们先来说明什么叫 concurrent。那到底什么叫坑 current呢?concurrent的意思是是这个。

Here。concur的意思这个。Concurrent意思是说。当我垃圾回收器干活的时候,你的业务现程可以继续。what这叫concur呢知道吧?并发,所以所谓的并发指的是GC县程和垃圾回收现程啊。

sorryGC现程垃圾回收是一个GC县程和业务现程。我主要有没有看你们认真听讲GC线程和业务线程可以同时在运行。原来都啥样,原来是GCE运行业务线程就得给我STW都得给我停住。

dtop the world。现在不需要了,现在没关系啊,咱家特别大,已经变成500个平方一栋别墅。你们姐儿仨在里边玩,随便玩你们的,你们在旁边玩着啊,我们我们这个妈妈爸爸爷爷奶奶姥姥爷作为摄像师哦。

sorry作为呃垃圾回收者就在旁边捡你们玩出来的这些垃圾啊,你们边玩,我们边边捡垃圾,边玩边捡垃圾。你们随便扔吧。那这时候就会产生一种什么现象?这时候产生的现象就是。我的应用程序永远有想要。为什么?

因为我业务现成在这里跑着呢,我当然有响赢了,所以这是concurrent的本质。嗯,不知道我说清楚没有。来能get到这一点,同学老师扣以。嗯。当然。这里面就会产生各种各样特别麻烦的问题。同学们。

你们想想看。我我我往这边一边扔垃圾,你这边一边捡,万一我扔一会儿。你呢扫描完这个对象说啊,这个对象是个垃圾,但是万一我一会儿又把它给捡回去了呢,对吧?他又不是垃圾了呢,你把它清掉不就。玩的完蛋了吗?

而且就重样的还有还有一个叫做万一我。比如说。我我我我我我我本来啊这个对象呢,你扫描它不是垃圾,但是我玩着玩着,我已经把它的连线给他剪断了,它又变成垃圾了呢?你又怎么处理?😡,就给标错了。

所以就会产生各种各样的问题。是不是啊,同学们。好,这是concurrent。我们先来介绍concurrent的这种呃开天地开天辟地的第一个啊。

就concurrent的呃呃。

系列 4:P9:【JVM调优实战】著名的三色标记算法 - 马士兵北京中心 - BV1VP411i7E4

okK这里。CMS。他是这么来玩儿的。他的原理呢也非常简单。虽然说从最底层角度讲,它由6个阶段构成,但是你跟面试官聊基本聊够聊聊通这四个阶段就可以了。这四个阶段分别是什么呢?分别叫初始标记、并发标记。

重新标记并发清理。11。1点来讲,他很容易理解。这里面最难理解的是这个阶段,这个阶段就是著名的三色标记算法。今天看时间吧,好不好?现在已经10点了。看到里。呃,这是。它的四个阶段四阶段是什么呢?

初始标记初始标记的意思非常简单,就是找到根儿上的对象,找到那些root对象。大家知道我们垃圾回收过程就是从根上开始找。先把这根上的对象找到这部分叫初始标记,注意它依然是STW的。

但是他SDW时间会非常短,为什么?😊,原来的SEW6时间是要你把所有工作全干完,所以它时间非常长。现在这个SW6时间,你只要找到根上就可以,根上对象毕竟没那么多,所以。这个SCW时间特别短。

一一般来说没有多长,所以没有关系。接下来就是最重要的阶段。这个阶段是什么?这个阶段是我们的业务线程继续,不管你有多少个业务线程,几十个,或者你们哥仨,你们几十三随便玩儿。你们在哪玩的时候,我垃圾回收器。

就在工作了。垃圾回收器开始工作,我就开始找哪些是垃圾,哪些是垃圾,哪些是垃圾的是垃圾。你一边玩着,我一边清着,我一边标记着啊,不能叫一边清着叫一边标记着啊,这个是垃圾,这个是垃圾,这个是垃圾。

这个不是垃圾,全给你标出来。😡,等我标好了之后,注意它一定会产生错标。错标主要有两种情况。第一种情况是。好好听我讲,原来这哥们是个垃圾。原来这哥们儿是个垃圾,但是呢运行过程之中呢又有一个引用指向头了。

okK他就变成不是垃圾了。这种的你后面不能把它给清掉,你得把它修正过来。还有的呢,原来这哥们儿不是垃圾,有人有引用纸箱的运行过程之中呢。好。引用没有了,它又变它就变成垃圾了。好,这是两种经常见的情况。

这块大家能呃听得懂吗?这块是最难的内容了,concurrent里面就是CMS里面最难的内容。嗯能能盖到吗?嗯。讲错了吧,宋海强。一定是你错了,你放心,我这不会错。凡是怀疑老师错了的,你们都错了。

引用没了,怎么又会引用回来,我一会儿讲给你听。😊,那个叫做先引用了,然后我们的垃圾回收器以为引用没了三色标记,我一会儿讲给你听好吗?引用没了也能引用回来。我告诉你。😡,虽然情况比较特殊,但是完全可以。

比如说缓存你命中了。然后你那些没命中的,你要清掉了,突然之间他又来了一个命中了。比如说你重写了finalize方法,原来死了对象你又给他复活了。😊,放心啊,我这儿没错,我这没bug。

成员的bug就像自己的内裤不会展示给别人的,放心。Okay。总而言之,会发生两种情况。就这两种。这两种情况最终都要进行修正。好,这个修正过程要重新标记。修正过程不能让原线程继续,业务线程再继续的话。

那你不断的新错误再产生了肯定不行。所以从整个的CMS角度,一共有两个阶段是STW的,一个是初始标记,一个是重新标记。毕竟出错的不会特别多,所以重新标记的这个STW时间也不会特别长。好。

最后呢我标完了确确定标清楚了。这就这个哥几个是垃圾,那哥几个不是垃圾,好嘞。并发经历清理完了之后,下一步。好,这是大体的过程,这里面有很多细节,最差的最多的细节就在这儿叫做三色标记算法。

著名的三色标记算法。勾浪采用什么算法?狗浪。知道吗?三色标记。是。那小点点问SW了怎么能出错?大哥,你看看这是SCW吗?我说的是出错,是在这出的。嗯。😊,三色标记勾浪也是啊。

所以你不要说那个java超勾浪,别扯。好嘞,下面我聊我我详细给大家讲。这个问题可以吗?就这讲这有点难。今天我告诉你,我讲完三色标记就没有时间讲G one。

就没有时间给你们讲G oneZDC she能doahexllent。你是想听Jg还是想听三色标记,你们自己挑。都要。Okay。我能做广告吗?我告诉你想听全了,找老师报VIP来。我VIP啊告诉你啊,那个。

我先不跟你说,我们VIP课程有多牛,我就直接先跟你这么说。😊,就是我们的VIP。全中国我们要说第二,没人敢说第一,我VIP课好吧。呃,内容先给你解释,我们VIP课有一个非常显著特点。我们叫做快速有效。

注意快速这件事儿超级重要。叫做不仅有效而且快。有效。而且快。快点写错了。姚急,我今天肯定给你讲完,不管是三色。还是。还是还是Gone哪个都成。快速有效。这是我们原来VIP学员,全部都是真实的截图。

你自己随便看。非常非常的给力。呃,我我我大概给你打开几个看看,好吧,这这好像是最近的啊。如果你要是跟着我们。

每天的课在跟的话,你会发现这个页面会天天更新,每天都有新的这入职一车涨薪的6K啊,课程没有帮助啊,课程是很有帮助的。其实不只是面试,实际工作也很有帮助啊。😊,这个是我们呃一个女孩入职京东,涨薪50%。

呃。其实给大家看呢,你就你会发现呢老师呢除了给大家讲课之外,还给大家。告诉大家怎么去面试,怎么去对付面试官,怎么去跟HR聊啊等等。最关键这哥们儿这姐们儿有点后悔。果然像你说的,我是少要了少要了。

我是我要少了,一分钱没砍,直接成了啊。他原来十6要了23直接成了,要太少了,亏了。一年运维转闸了,低薪涨到30万。他原来那个他原来是一年一年的运维经验转到粘了。经过我们我。

然后赵老师周老师在一个群里头不断的辅导他,看见了吗?这一个群里头是6个人,6个人里头只有一个学生,剩下全是老师。然后一年日月为准的占了,地薪给干到了30万,这就我们课成特点啊。课程特点叫做特别快。

然后呢又又有效。好,听我说,我先简单跟大家聊一点点课程的特性。不过别着急,我一会儿就会给大家讲后面的内容。呃,所以我们课程来讲呢,有这么几个特点。第一个特点呢叫做课时特别长。我们课时超长。长到什么程度?

我们已经讲完的课大概是已经是2000个小时左右。

这个是我们讲完的课啊。这是我们讲完的课。如果要从头拉到尾的话呢,基本就没完了。你你你可哎。啊。从最基本的。Yeah。Yeah。到。太多了。继续啊往下拉。到进阶的到网络。

到Junit注解反射前端的没稳的嗯多线程的啊。我今天给大家讲的呢,实际上是JVM的部分啊,所以这里面每一堂课都是两个小时,这这内容非常多啊,reis zookeeper。

myxico高并发activeMQsp boot一级流量电商嗯n。好,ELK区块链my catDBC,然后架构算法项目,网约车第一节二版3版TDDspring cloud。然后整个架构大数据还有。好。

不玩了,不演示了,太多了啊。好,我跟你说,就是这个课的特点呢,这是第一个特点就来了。😊,第一个特点叫特别长。好,第二个特点呢叫特别深。因为只有成才能比较深,原因是什么?你课时不够,我想跟你讲特别深入。

那不可能的。第一个超级长2000个小时以上,有同学可能不明白这个概念。我直接告诉你,同学可能大多数的凡是跟你说,每周四每周三次课,每次2小时,你自己去算去。他们这课讲一年差不多也就300个小时左右。

我们是2000个,是它的7倍。我们要照他的速度讲,得讲7年才能讲完。但是我不是这么讲的,我们讲的非常的深入,我们只有讲的课时特别长,才会讲的非常深入。我会深入到每一个算法。

比如说我今天给大家讲的三色标记,我们要给大家讲的G one,我会跟深入到每一个算法,每一个源码,知道吧?深入到那个hosport的源码来跟你聊G one里面到底是怎么进行分区的。好,听我说。

讲的这么深入,同学们的第一个观感一定是说大哥,你这个太过分了,我怎么才能学得完啊?就这是我们课程最大的特点,就是我不需要你学完,你也不要学完,你慢慢学。你首先拿到你想要的。

然后再跟着老师慢慢练这辈子你就跟定老师了,永远让你站在技术最前沿。我们怎么教你呢?这么来教。你入学之后。我我们有呃专门的老师来了解你的什么呢?了解你的基础。了解你的诉求。帮你设计一条最短达到目标的路线。

沿着这个路线进行一对一的定制学习。可以这么说,我们是一个大学的选课制,一堆的知识点。一堆的项目。作为老师来说,你想拿到一个,比方说你想涨薪5000最简单的要求了。3个月涨薪5000。

老师就给你拿出A加B加C,再加一个项目搞定。举个最简单的例子,作为社招生,你已经参加过工作了,你想涨新的6加2。3个月之内搞定。好,作为。比方说大学生,我想进大厂7加1加1。

最好的是大二和大三跟着我们练,这是最好的时间。基本上你学校不是太差的,保定大厂。好,老师,你说我特别着急,我已经辞职了,我想短时间内回到行业,涨顺带涨点薪水,一个月之内3加1搞定。老师,我想全系列提升。

我们MCA架构师带着你一个项目,带动你N多个知识点全系列提升。老师,我零基础。A课程一直到MCA。从零基础一直到进阶半年左右。老师,我那个想进某一个特别牛叉的厂子,他特别看重算法。左老师的左神算法课。

左神算法从最基础的数据结构,最基础的算法开始。到BAT体格的刷题班。搞定。好,这就叫做一对一定制学习。全网唯一,没有第二家。笑容。我的人说老师这是能行吗?自己看效果就行了。

25岁英语专业5天突击进携程,携程回复19乘15啊这个。他那哪说了5天,我记得啊。看了吗?5天后你面试携程,也是想突击一下,定制一份学习规划。对,5天突击携程就直接给了19乘15。有逼吗?为什么?

因为我告诉你了,注意先学脉络后学细节,老铁们。学习方法叫超级重要。滴滴神舟两个offer。大专生不幸错过阿里,暂时入职申通申通,他为什么不幸错错过阿里的?我告诉你。

当时啊他在入职申通的时候面试阿里的那个HR给连着给他打了8个电话,他都没接着。惨了,不然就进阿里了啊。嗯。阿里三面的时候正在四面的时候打了两两次,8个电话都没接到,都在面申通,太惨了。史上最惨大专生。

三轮面试进入腾讯。这是明哥给做的指导。其实从这里面你会发现,我不知道大家发现没有,在这里面呢会有老师的大量的指导过程啊,我的民歌的连老师的、周老师的、曹老师的都有。左老师的啊全有。呃。

有很多时候呢就是大家伙在学习的时候,很多人的学习他没有方法。他也不知道把时间一小时,我该用在这个地方呢,还是用在这个地方。我是去抠这些细节呢,还是去掌握整个脉络呢?他根本不知道他不知道重点。

所以全部都浪费了,太浪费了,不要这样。在咱们这儿有一批牛逼的老师就直接带着你。今天你该学啥,明天你该学啥,啥你都不用想,你人过来,我就让你长薪,就这么简单。你只要人过来听话就行,你听话我让你学啥。

你学啥剩下的什么怎么面试,怎么写简历,怎么优化简历,怎么去投递这件事你全都不用想,全交给老师就行了。我就需望你做到一件事,听话。以前有人已经吃过这个亏了。我记得我们有1个30多岁的女生,知道吧?找找。

哇,这个。看到吗?哦,这是39岁的一个呃小伙儿,这是大大专专科学历。薪蕊翻了一位啊,他只要听话就行。OK。😊,是。还有一个看看这个了吗?38岁大龄女成员,年薪4万,听话就行,就怕有那些不听话的。

就是我因为我知道我作为老师这么多年的教学经验,我知道你应该把重点放这儿,你就拿到大厂offer了。你应该把重点放这儿,你就轻松涨起薪水来了。但是你是自己是不知道的,我一会儿学他一会儿学习,一会儿云计算。

一会儿学习一会儿大数据,一会儿学习,一会儿后端感了兴趣聊聊前端又有这个有时间了,聊聊shall,你扯淡呢。集中精力工益点。好,把这点躬身了,比什么都强。而这一点功在哪里,每个人其实是不知道的,我们知道。

今年重点。大厂的重点是四个方向,你们知道吗?我一说哎,我知道你不知道。所以老师给你带来的是什么呢?你原来是带来的你的你的你的这种。呃,发展机会,改变你人生轨迹的机会,知道吗?什么叫人生轨迹?

就是你原来是这种路线,如果没有人带着你没人指点你,你就是这种路线慢慢往前走,到一个程度开始往下跌。跟着老师走,跟着我们20位左右的认准了。因为课堂上有很多很多抄袭我们的,知道吧?

但是他们没有这种这么多的老师,也没有呢一线大厂的这种工作经历。一线大厂工作经历很容易就能找着的。比方说他说在阿里工作过,你问他花名是啥?阿里一查就能查着,知道吗?比如说你想问我们老师的画面。

随便问黄老师画名博熙自己去查去,一定能查着。我们20位一线大堂的老师带着你,你的人生曲线是这样子的,所以别后悔。千万千万抓住呃,就是跟我们跟跟我们飞的这个机会。OK。呃。

我们课程呢大概是每个课时在55块钱到7块钱。呃,你不要看总数,因为人家的课时是300个,知道吗?人家课时50005000多到6000多,但是你自己算一下,人家每课时是20块钱到30块钱。

我们每个课时5块钱到7块钱,性价比超高。同一课堂都受不了。同一课堂说不行,你们再这么玩的话,我不允许你们送这个送那个,不允许你们把这么多的课时怼在一堂课里。Sorry。到目前为止,腾讯可能受不了。

一直在逼我们拆。目前还没有还没有拆拆开。如果要拆开的话,我告诉你MCA会拆成P5P6P7P8。四个可,但就不拆了啊,现在不拆。全给到你,因为有的人的基础不一样,有些人认为他具备P7冲P7水平。

实际上他连P5的内容都没掌握住。我可以这么说,在座的诸位,99%的人有一些屁股的最基本内容,你没有掌握住。比如操作系统底层,比如我就问你0X80的标用过程。80终端调研过程,这是阿里P9面试的一道题。

你能答出来。很多很多人都答不出来,好吧。哪个计存器放的什么参数,你能答出来,你答不出来。这是我们听话的同听话的同学看到了吗?我特别想在公开课的时候能够多影响一些人,让他们在职业生涯规划中尽快走出迷茫。

但是人家会以为我是兔儿,所以只能先忍着啊,你别来了,没事儿。托儿呢到处都有,不用,我们这没有托儿,也不用当托儿,不需要VIP学员来这当托儿,直接看结果就行。半年涨了9K的。

滴滴快手双offer的。这个没有加载完啊,加载完的话就太多了。还有像特特别有人的,就特别的那种那种那种有什么呢?有有有疑问说老师我大专能进大厂吗?

我有很多每次每次讲这课的时候都有都有人问我说我大专时候能不能进大厂。有这种疑问吗?有这种疑问给老师扣个一来,我认识一下。陈润基对,石家头,没错,刘志祥。我给你搜一下啊,我不太想跟你聊行还是不行。

我给你搜一下。

这个是大专生,不幸错过挨里赞术这进行申通的。其实你刚才看到过了。阿里已经给他在四面了,能不能进啊?有绝对有机会。这是大专学历,收到多家大厂的offer看了吗?一鸣哥,非常感谢帮忙P开简历。

也感谢我们马上教育的课程啊,接触到不少的东西。😊,按照周老师的说法就认知偏差了。经过三周面试,我目前已经收到了不少的offer,后期我会继续学习,真是想不到大专学历的,我也不再只是那种中小型公司。

喊会去面试。所以小伙伴们啊,有很多大厂有一些大厂啊,是他是不太在乎学历的。一线大厂,我们认为中国有一中国IT界有10家左右的一线大厂,他们是头部。那么这十家大厂里头呢,有几个是不在乎学历的。

分别是阿里、京东、滴滴,这几个不在乎。当然,再往下那些二线的、二流的、三流的,也有好多不在乎的。小伙伴们,大专学历的,你已经改变不了你学历的情况下。请记住,加强另外一条腿就行了。技术。

说着我老师忍不住给你们看看点简历啊,大专生的简历算了,一会儿再说吧。呃。这是大龄的大专生,从没工资到就业啊,这个年龄比较大了。

30毫几了啊。大专学历不到一个月,薪资翻一倍的啊。

还有好几个就是大专拿拿两个滴京按那个京东跟滴滴两个offer的,呃,可能没记录大专生这件事啊。所以各位同学们,你们记住这一点,就是说学历呢在你改变不了的情况下,加强另外一条腿儿,没毛病。

你千万不要自暴自弃,大专生有的是机会。如果大专生候有机会,你们想想你作为。其他的这种学历的那就更甭题了。这是32岁大专生,这哥们拿了60万到70万年薪。有同学说怎么还不固定,因为他拿了9500股票。

这股票的来回的升降,他不一定。这个大专生。你仔细看看他的个人优势,他的写法,这就是学完我们课程之后的轻松可以写上去的东西。😊,瞅一眼。5年夜样开发管理经验,这个有点夸张,负责项目日活300万。

注册人数1。3亿。这个项目上的呢有点稍微有点夸张。高吞土低延迟分布架构分布分布经验。一会儿我有机有时间我给你介绍介绍我们课程内容就知道了,这是我们的一个非常擅长的一个点。呃。

JDK的各种集合队列所多线程高并发NL相关底层制能原理,这都是我讲的。数据结构与算法设计模式。我跟左老师讲的GC垃圾回收算法,丰富JM调学经验。我现在正在讲给你们听的。5条大厂就已经向他开门了。

660万到70万。当然我们课程要是学完是什么水平?我课程学完大概大概是这种水平,你真要能学完。大概是这种水平。自己看。给大家时先读一下吧。你真要学完啊,大概是这种水平。没有精通的废话,你跟着老师学。

你就精通啊。你要听完我这个M课,不敢写精通的那你这是是你太太太把老师看的太低了。😊,还是一个啊,就是我们这儿的课说第二,没人敢说第一。随便倒。不继续讲课了啊,讲讲讲讲讲。😊,看完这简历我们就讲行吗?

还想看吗?不想看我就关了,想看我就带你们看看。😊,简历我可不敢写精通,懒洋洋,恭喜你,你以后尽量的什么都不要写精通。然后我的学生们都写精通,你猜猜看谁会拿到面试机会。傻不傻呀?Okay。上什么怎么样。

随便他上什么下什么随便好吗?我不是针对谁啊,是针对所有人是吧?嗯,有有的人可能呃广告做的比我们好啊,这个影响面比我们宽,但是就课程质量随便玩。你拿大腿想想,我这的老师可是来自于BAT勾一线的。

而不是在线下干了很多年来回来去翻来覆去讲的那些老师,好吧。我们说还是那了啊,我们要说第二,没人敢说第一。好,看这里。就是你你学完用整体课大概是这种水平。分贝系统架构。海量数据。高并发系统架构。

高可用加构高性能架构。O。项目水平大概是这种技术水平,大概是这种。好,这个小伙拿了多少钱?阿里的P7加。80万底薪加40万股票,120万每年。恭喜你最近跳槽了。叫做薪水,非常的具备竞争力。

叫做200万左右加股票。Okay。当然他有他的天赋,有他的优势,他的学校比较好。但是我想是这样的。我作为我们老师讲,我不管你的优势天赋,那是其他方面,我只负责把技术给你们讲到这种深度。听到了。

就是我呢我们我们这的老师就负责一件事儿,把技术给你们讲到这种深度。就行了。他这个学历是本科,但是他学校比较好,好吧。但是你就想吧,你就算不是科班,你薪水比他低。你拿他3分之1薪水行不行?

啥学校这有点那个隐私啊,反正不是清北啊,但是他学校确实也很不错嗯。嗯。你就想吧,你就拿它3分之1左右的,然后慢慢以后慢慢长嘛,怕啥?😡,核桃花生礼哇塞。你们是怎么猜出来的,怎么那么牛刀。😊。

好了好了好了。😊,呃。说这么半天呢,今天晚上呢,金金明金明吧金明我们都有一个秒杀,但你不要错过啊,我今天晚上既然是第一天,其实第一天没想打广告的,结果聊着聊着开始打了广告,打一点就打一点。

我们今天晚上金九涨薪剂。我们MACA马兵认购架架构师的这个课。涨薪最快,20天内让你涨最快的。最慢的90天。最高涨薪500%,这不是说着玩的。有同学说老老师涨薪还能500%的涨呢。他我也奇怪呀。

但是人家就是长上了,有一定的狗屎运,只能这么说。你找找这哥们啊,留着呢。你像这种5K涨到15K的这这都算是相对简单一些的啊。就是那个这么这么跟你说。

其实这里面帮助你能够走出来的最重要的一点就是老师在群里头真的是手把手。步步指导你哪步没走通的,没关系啊,都有一堆牛人带着你。找找。找找那哥们儿啊,就就这个应该是这个。啊,问我CMS三个过程。

三色增量remarkFDC。啊,不不不不是这个哪个来着?哇。找不着了,找不着了啊,你你们你们自己可以去找啊,这个这个这个界面就是这个呃这个网址就在这儿啊,你们自己上面看就行了啊。

每一个都是非常真实的一个聊天记录。这聊天记录里面呢,你们要体会老师在这里面花的心血,你知道吗?😊,你会发现这都是一个很很明显的一个互动过程。我觉得呢教知识这块我们肯定没问题。

但是其实最重要的呢是在服务这块。就是我们的这个服务呃,应该也是number one,好吧。嗯,他是大概原来在长沙拿5。5K,然后跳到杭州,直接拿了25。接近5倍啊,就这么强。呃。

今天晚上呢有10个秒杀名额,0点之前秒杀截止。今天晚上找腾讯申请的8000的大额优惠。如果我们要不申请优我们课程呢是非常贵的。今天晚上申请完大概5到7块钱一个课时1万1万多的课啊。

报名呢送你一个樱桃红红豆键盘,你要是不要可以给你折现。9月9号首次开启的源码班。今天晚上报名送了。15号我们开始讲多线程的第二版左老师的算法全都有。好,如果有有有有意愿的去找我们小姐姐。

骚or扰他们一下,好吧。随便找哪个小姐姐都可以。当然你已经加上小姐姐,就不用不用再找其他的小姐姐了,不要三心二意。啊,要用成专业OK。折现多少钱,你问问小姐姐,这个是他们市场部定的OK。好。

我呃是这样啊,你们骚扰小小姐姐,我来我去上一个小小的厕所。回来我给大家讲三色标记吧。三色。今天讲高兴了,我讲完三色之后。在顺带的给大家讲讲G oneZGC Sheandoahepllent。可以吗?

要可以的话,给老师扣个一。一般上课什么时间?晚上8点到10点,周末所有的时间。就我们课呀。我我我我觉着啊你们一定要擦擦亮眼睛,一个是什么什么什么点呢?就是呃现在有好多网课。

这是肯定的网课呢有很多是每周就三次课,每次就2小时。小伙伴们。同学们,你们拿大腿想一想,每周三次,每次2小时,他得讲多少年才能达到我们课程量?这种呢想讲深的不是扯淡吗?怎么可能?我们的课是怎么上的呢?

这是我们一周的课表。嗯。这是我们一周的课表啊,这周课表还不算不算多的。我们课表一周最多的,找找看上上一上一周的这是上一周的,看到了吗?每天都有课,每周末都有课。不断的在更新。当然这是我们课程特点。

我们课程特点就是特别全。所有点基本全有,然后每个点都在独立更新。更新更新更新更新。然后你需要的时候帮你组合,组合好了之后,老师再带着你整个一条路全部走完。这周还不算太多的。这周呃今天晚上好像没有那个。

周二那天没有没有没没有VIP嗯。

呃。慎掉忘了啊,我我我我我我去我去拍空一下膀胱,大家稍等我片刻。5分钟最多5分钟。在这个时间段找一个别的老师算了,你你们稍微等我一下啊,回来我再跟你讲。三四标记今天讲高兴了,都给你讲完了,好吧嗯。😊。

这个膀胱不足以伺候你们了,得去排空一下。🤧。Okay。Yeah。Yeah。嗯。Okay。嗯。今天白天呢睡的比较多,我跟你说,原来呢都是基本上我晚上就讲俩俩时课。呃,2小时算多了一个半小时。Okay。

今天白天睡的比较多。今天晚上讲开心了,主要你看。今天晚上又失旭东在。石旭东啊,哎,正是因为有你在。今天晚上多讲一些,好吧。Okay。呃,课程是怎么学习的?直播加录播,老师一对一辅导。你带着人来。

然后老师让你干嘛你干嘛?老师说这周把这个掌握。你就把这掌握住,老师说下周把这掌握,你就把这掌握住搞定。你说3月我想涨个新,涨5000来就是了。在这儿还没有人长不了新锐的,好吧。一对一是每周几次辅导。

有问题随时你一周有10个10次问题。就十次一对一。你如果一周有100次问题,就100次一对一。如果说想去快手呢,一共多少钱?一共1万多块钱吧,一万出头嗯。MCA对。我们要推我们自己的标准了。

因为我们讲啥他们都抄,你知道吗?我们说我们叫P8P7啊,他们抄我们我说我们说我们说P8,他们抄,我们现在就是整个java培训会界的标准,知道吗?

我们现在推MC叫马士兵 certifiedtified architect。那你再抄。2。对。😊,XCAX什么意思?X战警吗?😊,Okay。不好。你出个主意。怎么灭怎么用得抄袭。关紧抄完了之后吧。

他们就一个老师还号称自己有2000多个课。😊,拿大腿想想大哥。一两个老师三四,然后每周就讲三次课逗我呢嗯。😊,Okay。几个月可以去快手。你你说的非常特定的一个企业呀,我跟你说。

万一这家企业现在正不招呢。这个不能把自己锁在所有鸡蛋放在一个篮子里啊。我希望你面对的呢是整个这种水平的企业,你懂吗?我们整个企我们整个呃。课程呢是这种就是一流大厂。一线呃一一线城市一流大厂的水平。

至于说。二流的三流的,你降维打击就行了嘛,无所谓的事儿啊。快手现在只招外包。对啊,你要万上万一遇上人家不着呢,你你不惨了嗯。你让我想起了哪个老师?Yeah。怎么怎么让你想起的,我怎么没get到嗯。😊。

说好的回来就讲三次了。没错,你你先让我把这个补充点补充点营养行吗?先补充补充啊,毕竟老师6060多了。一口气讲太多也也够累的啊。嗯。这个课程是不是需要有很多年的经验,不需要没有从零基础开始的。没必要。

嗯。你来就是嗯。来就是了,好吧,解决你所有的难题就在今天晚上。我操60以为40对,你以为的对了啊,开个开个玩笑,开个玩笑,没那么老啊。😊,嗯。7几年的70年代人啊。😊,🤧小姐姐头像好漂亮。

这都是小姐姐的真人,不是头像。好。课程太深,听不懂咋办?从浅的开始。所有人啊都是从浅到深的。每个人都是从零从零开始慢慢走到这么深入的。你们知道你们你们为什么喜欢听老师的课吗?因为老师讲课也下功夫。

还是过期了就没了。呃,如果是录播,是终身都有的。如果是直播的话呢,呃现在腾有可堂限制我们有没有我们原来是那个终身制的会员,你都可以终身听直播,但是。现能有可能限制我们是两年。然后第三年。

你想继续听怎么办呢?88亿年88块钱,大哥总得有点仪式感啊。听得懂,但是过段时间就全忘了。恭喜你。说明你是个人。你要是听一遍全记住了,那你就不是人,你是神。嗯。嗯。😊,没关系啊。你拿张纸。

把重要点全给我记下来,没多少,老师都帮你总结好了。😊,你就干一件事就行了。😡,面试之前拿出来看看。吃饭之前,饭前饭后。变前变哄。只要你别你别变后变后变后用了就行了嗯。Yeah。运维需要往这方面转吗?

现在感觉上不去了。你看你多大年龄。如果你年龄比较大了,我建运维呢往两大方向。第一个叫做。那个CICD知道吧?

就是和开发结合CICD叫呃continuous integration和continuous developmentCICD这一大方向。第二大方向叫安全,这两大方向运维可以走。还还有还有涨新机会。

Yeah。は。便后用的饭前用啊。VIP课程没时间上怎么办?😊,其实我们VIP不太多,多数人。不会有所有时间全赶上。但只要效果到位就行,我觉着不用赶所有时间。没看能涂啊,就这样涂。这上我们课的到课率。

你看这哥们儿这倒客率,这哥们儿到课率是0。7。😊,嗯,1000堂课来7堂。但是整体完成度是百分百,看到了吗?没关系啊,你那个没赶上直播看录播嘛,录播还可以两倍速呢。而且你跟老师在群里,你有啥问题。

直接问老师就行,不用担心没有互动的,放心。

Yeah。你追求的是效果。Okay。10个,今天晚上。放完就没,不知道还剩几个,所以有需要的你抓紧找丨小丨姐姐啊,我喝完这点水,咱就开始下一步。最后一口啊。让我稍微吃点喝点。开始吃播是吧?2牛9随便看。对。

没错。腾讯课堂啊在哪儿?腾讯课堂。完成度什么概,有作业吗?呃,我们有的课是要留作业,有的课没有这个分课不一定。老师三七女怎么发展?一对一指导,我是需要了解你的背景的。就是你以前是做什么的?做了多长时间。

有什么项目经验,从哪毕业,分哪个厂子,哪个城市,这些都很重要。你这么简单一句话,我很难跟你说清楚怎么发展。🤧嗯嗯。Yeah。那就要我最后一口喝完,吃完喝完我就开始啊。要完三个月涨薪后。

再给跳槽搭成了的一对一指导,没问题。于是知道知道你到底。就是你相当于啊这1万多块钱买了什么呢?买了20位导师,这20位导师,你想听他们过来人的一些建议意见来就是了。像这些都是在阿里呆过的。

美团呆过的oracle呆过的银行呆过的。亚马逊外企待过的这种双大厂都待过的。就是这些人给你两句,你很可能就少走了很多弯路,你原来得绕着弯的才能走到这个位置。现在你只要直接就过可以过来了,少了很多坑。

这个不值钱吗?太值钱了啊。而且不要担心这点学费,第一个学费可以分期。第二1个,你这学费谁掏的?😊,三年之后下一个不是sorry,3个月之后下一个。接盘你的场子替你掏的。

因为3个月涨5000块钱是我们的基本承诺。我们对你的唯一的要求,让你学啥你学啥。老师,明天讲吧,要洗洗睡了,你先洗洗睡,我先讲啊。😊,好了,我们准备好了吗?要找丨小丨姐姐找丨小丨姐姐啊。

不少道小姐姐的我们准备好。我们开始讲比较难的难点,三色标记,三色标记超级难。我要讲完的话,基本俩小时。但是我先给你讲入门知识,你了解CMS到底是怎么玩的,好不好?😊,准备好的老师扣一来。哎,我跟你说。

老师从我这讲课,我就喜欢特别难的东西,给你拿什么来演示呢?动画。嗯。嗯。嗯。Yeah。Yeah。Okay。放心吧,我这讲的课你别的地儿都没都听不着的。😊,那个。我跟你讲三色标记,也许你在网上看到过。

但是你想在网上看懂三色标记真心没那么容易。但是我通过给你动画的演示,很容易你就能理解。嗯。来准备开始。下面我们要聊的是三色标记算法,用在什么地方?并发标记阶段。注意是并发标记。他还没有清理。

听我说还没有清理,只是在标记。回想这个场景,你们哥仨在这里不停的扔线团,扔线团,扔线团,垃圾回收器,在这里不停的找。哎,哥们是垃圾吗?哥们儿是垃圾吗?哥们是垃圾吗?在你一边扔一边找的过程之中。

会产生各种各样的问题。他的这个扫描过程是这么来扫描的。由于这个县程是隔一段时间才能运行,隔一段时间才能运行。所以你必须把上一次运行阶段要保存下来。上一次运行扫描到这个程度了。

下一次要在这个基础之上继续扫描,什么时候扫描所有的完事结束为止,然后才开始清理。这块大家能听懂吗?我再强调一遍,这个扫描过程是本身分了好多步,而且是不确定的。为什么?

因为现成的运行时间是由操系统来进行调度的。它调度的以及执行的时间片时间长,时间长时长都不是固定的。linux内核采用的叫CFS线程调度算法叫completely。fairness strategy啊。

complete fair strategy叫嗯嗯嗯嗯完全呃呃公平算法。嗯,它并不是平均分配啊,这这是完全两个概念。这是我这是我在讲操作系统课的时候讲讲的概念。在这就不跟你说了。总而言之。

我们开始对整个对象图开始产生标记的时候,垃圾回收现场在这里面会议运行好多次,每次运行完这个时间段段之后,一定要把这个。当前你已经标记到哪里了,给记录下来,我标记到这个对象了,还是标记到这个对象了。

还是标记到这个对象了,给记录下来。😊,这个概念能get到的给老师扣个一,然后下一个阶段再回来的时候继续。😊,那么怎么才能记录下来呢?它采用的方式叫做三色。标记算法。VIP课人也聊天嘛?

VIP课上就不怎么聊天了嗯。😊,关客聊天聊的稍微多一些。好,下面我们来聊三色标记。我们首先明白第一件事儿,什么叫三色。三色的意思是,在他标记追踪整个对象的过程之中,如果一个对象。他自己已经被追踪到了。

就是顺着线我们已经访问到他了,已经捋到他了。找着这线头了,并且这个线头的孩子们我也标记完了,我也标记过了。好嘞,这哥们儿叫黑色黑色对象有一个特点,就是当我下一次垃圾回收现程再回来的时候。

黑色的对象我就不再去扫描了。不再扫描。黑色对象不扫描了,为什么?因为他标完了,他孩子也标完了,那没必要再扫他了。所以这个呢叫黑对象。叫black。好,那我们在扫描的过程之中,我扫描到黑色了。

也扫描到他的孩子了。但是他孩子我扫完了,像这种的,本身他扫完了,这哥们儿是个不是垃圾啊,不是垃圾,扫完了。😊,但是他的孩子我还没扫到。这种叫灰色。那我们当我们垃圾回收线程暂停之后,再次回来。

发现灰色对象的时候,他干一件什么事儿呢?他不去扫描他自己,只去扫描他的孩子就可以了,继续往下进行。Okay。YeahYeah。古城我说的是标记清楚。标记清楚的标记过程不就是三色吗?哎呦我的天哪。😡。

这个累呀三色是解决什么问题,不就是标记吗?我第一句话就是说三色是解决标记还没有开始清除。😡,好,能能继续的给老师扣个一。那白的是啥?白的是没有便利到的节点。这叫白。Yeah。嗯。😊,这个。Hey。

Bethley。这就是三色标记。当然。Yeah。有同学会说。那个老师我我我以前啊讲课的时候,真的有人问我说。老师,这这这这颜色是怎么标标识的呀?这这个怎么能把这个对象给给他染成黑色呀?😊。

这个呢我告诉你啊,你可以拿一把刷子把那个对象呢蘸点黑色的漆,就可以把它染成黑色了。听明白了吗?H。黑油戏讲的就是黑色嗯。嗯,原来是这样子的对。开个玩笑啊,我觉得问我这个问题的人应该是没写过程序。😊。

大哥,你的年龄是50,你的年龄是15,你怎么标记的呀?不就是一个变量吗?黑色白色、灰色怎么标记的?我告诉你,就是在对象上做了一个记录。比如说。有两位01代表它是黑色,1一代表它是灰色,10代表它是白色。

不用我讲了吧。那有同学可能会深究老师啊。他这个011011这些标记。是放在哪里的呢?😊,恭喜你,你问到了一个触及灵魂的问题,它是放在了这里叫m word。在m word里面。

8个字节的m word四个字节的class pointer,N个字节的instance data以及N个字节的padding。好,就在这里。这里面有四类信息,第一类三类信息,第一类叫锁信息。

第二类叫hash code。第三类叫GC。这个GC就是CMS的脑袋记录在这儿。Okay。又来了m克 word废话,前后都是相通的,好吗?怎么着,那还不给你来买味的了。嗯。好啦。当然那是另外的知识体系。

那个我也会讲VIP课里也全有。我们今天先来这套知识体系,这个知识体系是这样的。自己标完孩子也标完黑,自己标完孩子没标完灰。还没标到的白好。由于在整个标记的过程之中。

它的不阶段运行以及我的业务线程也在不间段运行。那么他会发生什么情况呢?第一种情况是这样子的。当我们经历一次时间段的垃圾扫描之后,扫描到这种程度了,还没来得及扫描到白色对象的时候。由于我业务现成的运行。

我B指向D的引用消失了。就会导致一种什么情形啊,就会导致我扫描到B的时候,找他孩子,本来我要扫描到D呢,扫描不到了。地会把我们被我们当成垃圾,他没有便利到。本来应该便利到。但是还没有便利到了。好。

这种情况会产生什么严重后果吗?不会,没有关系,大不了啥呀,大不了它就叫浮动了。你下一次我再次扫描的时候,就会把它当成垃圾给找出来。这个没有关系,所以这种情况没有关系,听懂了吗?最严重的是另外一种情况。

仔细看。这是最严重的情况,认认真真看理解了这种情况,理解它是怎么解决的,就理解了CMS。Okay。看这里。扫描几次。你扫描多少次,总而言之,你整个对象图扫完了为止嘛?你所有都扫到了,全都变黑了。

那就是扫描完了,这跟扫描几次有半毛钱关系吗?我刚才跟你说过,多线程线程的调度是被操作系统调度的,它调度多少次,每次运行多长时间,这事儿我们管不了。改到了吗?Yeah。好,我们继续。B纸箱D的引用。

这个时候注意看,在我们正在扫描的过程之中,我扫描完黑色了A扫描完灰色了,B,还没来得及扫描B的孩子D。这时我的业务逻辑开始运行,B指向D的引用。消失了。与此同时,A指向D的引用增加了。来再看一遍。

B纸箱D的引用消失了。A指向D的引用增加了。同时发出了这两件事儿。来,你猜猜看。再想象一下啊,在我们扫描完A之后,经过一次扫描一个线程,那就围绕线程运行了一小段时间。A扫描完了B扫描完了D没有扫描到。

下次回来的时候。你会发现发生了中间发生了这种情形,业务线正在运行的阶段,A指向低的引用产生了B指向低的引用消失了。同学们,你们发现没有?当我们下一次垃圾回收现生再回来的时候。

如果我们不对这个问题进行修正的话。还记得吗?A是黑色的。我会去扫描他的孩子这个地吗?不会。那我B本来呢能扫描到地,但是由于它的引用消失了,那我还能扫描到这个地吗?扫描不到。因此,这个D既然扫描不到。

你猜猜看是不是会被我们当成垃圾呢?所以回来的县城如果不对它进行修正的话,这个地会被我们当成垃圾。这个地不修正,就会把它给清掉。再看一遍,这是最严重的问题。第一次垃圾卫生现城标记到这种程度了。

在下一次标记中间。B纸向底的引销是A指向D的引用诞生。OK这个D就淡出了你的视野。你生了个野孩子,你们哥仨生了个野孩子,扫描不着。来get到这一点呢,老师扣一,可以继续的。嗯,go。好,怎么解决呢?来。

你们拿大腿想想怎么解决。应该把A的颜色清除掉,扫描不到是不是就不会被清除了,扫描不到的才会清除啊。大哥,你扫描不到的不就是垃圾吗?😊,对你看琼克杰斯啊,杰克琼斯啊,jackjones。

jack看人家是吧,大腿多么的发达,把A标成灰色不就行了吗?也就是说,如果有一个黑色对象,他的孩子又指向了新的对象的时候。你的程序必须得跟踪,如果这对象是黑色的,他的孩子。又指向了新的对象的时候。

OK要把它自己变成灰色,变成灰色有什么好处啊?变成灰色,就是下一次垃圾回收县城回来的时候。😊,会重新扫描他的海纸。修改B为白色,你疯了,这跟修改B为白色有半毛钱关系吗?小点点。所以这是。

这是CMS解决方案。CMS解决方案就是把A。换成灰色。白标灰就行了。看懂了吗?这种解决方案叫做 incrementalcrement update。所以三色标的是什么?CMS解CMS解决方案是什么?

应该都能get了。B要改黑色吗?B如果他已经标完,他孩子标完了,他自己就标成黑色了,这个无所谓啊。总而言之,你A改成灰色,下一次我回来的时候就知道哦,A是灰色,我又要扫描他的孩子好D又被我们扫描到了。

Very good。好。讲点更难的问题。还要讲吗?毕业这孩子对毕这个孩子已经扫描过了嘛嗯。

系列 5:P1:全网独家私人定制直播教学、N对1辅导模式! - 马士兵学堂 - BV1E34y1w773

课程大纲给大家看一下啊。

这个课程里面的话呢,我们把它分成大概是十个模块,搜一搜啊,也就是说在这一期里面呢,我们会主要围绕这些知识点,这些第一个的话呢是属于架构基础啊,就是会去讲一些基础内容。

然后第二个的话呢并发编程的一个核心原理,第三个的话呢像比较重要的PV每条U,然后下面的话spring的源码,然后还有包括spring cloud。

阿里巴巴就是微服务的核心,然后底下的话包括MYSQL性能调优。

REDIS实战啊,Rock q,然后三高架构设计以及网络与类型,也就是说这里面是十个模块,十个模块的话会有不同的老师来讲,可能有的老师可能讲两个啊,有的老师可能讲一个啊。

这个的话呢是根据每个老师的一个技术专长,来定的,大概的时间的话,我们是准备坐在3~4个月,就是一个季度,原则上面的话,我们不会超过四个月的时间啊,这个为什么可以做到这一点呢,是因为我们会把这些东西啊。

不是说全讲的,就是不是说把所有的这个面铺开,而是去讲,比如说当今比较核心的点,面试比较关心的点,以及现在市场上面这些项目当中,经常用到这些点,然后我给大家看一下,就是在下,因为我们今天是一个开张仪式。

所以我们的这个时间的话,大概就是只讲一个小时啊,然后后面的那个上课时间,基本上是每天晚上八点到十点,就是会上大概两个小时,然后在这两个小时里面的话呢,我们会为了去加强互动啊,我们在讲课之前。

我们会要求就是老师就是花一些时间备课,然后备课的同时也是在上课之前嘛,可能会把这节课的一些相关的,是一些预习资料啊,或者是你要需要注意的一些点啊,可以去就是提前发放到学员,通过班主任。

然后如果说有些学员跟班主任联系了,我要上中国班,得活的时间是固定的,每天晚上或者是说基本上每天晚上有时间的话,就可以来跟啊,然后同时的话你也可以看一下这个课的话呢,就是讲的内容适不适合你。

我们会在这个讲课之前发一些备注,就是可能上课之前,比如说有可能要上十分的源码,对不对,那可能有一个源码,有一个前置知识,spring的一些使用,spring的一些主体流程,至少能够防空。

OK然后我们再看一下吧,就是作为架构基础的话呢。

呃我就来讲一讲啊,因为大家平时其实作为现在面试啊,嗯基本上不会不得太浅,所以的话呢我们会抓一些常见的数据结构,就像这种帕奇麦克,像这种什么,我们常说的这个哈希麦克里面肯定有红黑树嘛。

所以像这种234树红黑树,然后一些集合SC啊,然后Mac啊,历史啊,这种集合的源码进行讲解啊,然后除此之外的话还会去提一下IO,另外的话呢像里面会讲一些比较常用的,像SYCHONNET这种关键字啊。

这种关键字的话呢,虽然原则上它可能会属于多线程,但是在架构基础里面他可能会讲的,那么就是说偏向于基础一点点啊,这是我们的第一部分,然后第二个部分的话呢,呃这是郑老师为什么会没来呢,郑老师还在注意看。

郑老师嘴上起个泡,所以说亲下说下对郑老师,反正那个住院的话也住了挺久的啊,我每天都打电话给他,然后呢我给他给就是给大家讲一下,因为做并发编程,其实它也是非常重要的一个模块,就是三大特性和原子性,可见性。

有序性啊,这些东西是必讲的,然后除此之外的话呢,会去讲一下cs wt cr各种锁,然后SYCHIZAKAK,然后range Mark还有包括比较核心的一点,像线程池的一些原理啊,另外的话呢。

还可以去讲一个比较经典的数据结构,叫康复的话,先买它的源码解析,所以这个呢应该来说是作为并发编程的一个,大体内容啊,然后第三个部分的话呢是GMGUM的话呢,这个部分是严振涛严老师去讲啊。

但是严老师因为他在我隔壁上课,所以我给大家讲一下,在JVM讲这个课的时候,会更多的体现像JVM的调优实战,就像这种大家可能平时在工作当中,就是问职员们大部分是原理问的什么方法区啊。

站啊堆啊这些东西对不对,然后这个课程呢就是会严老师也跟我说过啊,他备课的时候,更多的会嵌入他以前的那些,在项目当中的一些调优技巧,所以这个如果说同学们在工作当中,想去做这个调优的话。

可以去参与一下这个基本的课程啊,然后第三个部分就是这个上面的顺序啊,再给大家说一下,它不代表严格的上课顺序,因为我们要根据老师的一个排课,然后他的费课,他的计划安排定,所以的话呢这个我先把它列举出来啊。

然后像spring的源码的话,我们知道基本上源码可能是问的最多的,就是面试嘛,面试的话IOC啊,然后DI啊,然后像AOP啊,还有包括分配的事物啊,所以我们会抽一些重点来讲,因为源码课程讲的话。

可以我记得SPM源码别宝石,之前是讲了70个小时了,对不对对,那么我们肯定不会去做70个小时的一个讲解,所以像思科的源码,就会更偏向于面解决这种面试问题。

然后底下的话呢像spring cloud cloud,阿里巴巴这个我们知道像微服务其他附件很多,这个spring cloud阿里巴巴的话,我们会去,就是说在这一期里面我们不把所有的源码都讲。

我们会去讲一下拉克丝,然后ROBBY,然后我们还会讲apple fe,主要围绕这三个东西来进行讲解,然后可能到下一期,比如说可能过完年之后,对不对,我们可能会进入下一期。

下一期的话呢他们主要会讲一些其他的组件,包括像什么C卡,像一些其他的神贴吧这种东西,然后像MYSQL性能调优了,也给大家分享一下啊,就是MYSQL性能调优,其实这里面的话会去补一些常见的视频。

因为我其实我之前给大家讲过,MYSQL的话,它分成底层原理和实战上这两个部分,首先你要去搞定像底层里面的B加数索引,还有像他的一些执行计划,还有他的一个什么MVCC这种机制,然后有了这个之后的话。

你就可以去根据执行计划,然后进行对应的什么成本,基于一些我们的C口的这个条件的一些调优,OK所以呢这是我们的MYSQL的一个线程调优方面啊,要么我感觉我是一直在讲周老师讲一讲,周老师讲一讲,讲一讲。

我说好不好,对这个网络IO和NT这块,然后曾经有讲有一个IO精讲的那个版本,后边要如果再讲这个这个和net的话,就准备偏重于这个,因为前一次那个RBC起了个头,就有一个初级版本,然后呢0~1个代码写法。

然后呢最后重构这个分层,如果后面讲的话,其实我觉得就是咱们这个属于架构师进阶班,这个坑以及墙上那个东西就是特别偏离,特别死之类的,肯定会加特别多,老师都是在原有这个已有的一个模块之上。

向上拔高的一部分内容,无论从见解啊,归纳啊,然后他的一个一个深度或者源码,是思想上的这方面的输出,增强大家的一些话术,因为我刚才看到很多人说,这个课不是在美国抽出一些他以推理,都是这个拔高的一些东西。

就是所有的一些东西我们都会想到一个拔高,老师也是对老师的一个1111次考验,像那个网络IO的一个,你比如说我之前讲过,还有精讲的,有那个版本,然后这个课我就不会说,这东西再给你重复讲一遍,给你混入时长。

所以一定是继续的,把这里面就是把那个应该讲到二二十七,二十六二十四小时,把那个小时里边的东西我做一个总结归纳,然后给你做成一个一个一个思维导图,然后那个知识敲定之后,接下来就是延续这个RPC的完整体系。

因为听过昨天那个因为最近班我也说了,其实像呃分式治理和服务治理,就是这两个治理里面,然后其实他最最重要的还是和那个RPC这块,相关的RPC网络,网络这块连接上出问题啊,或者是对对方的不明确性。

协议上出现的问题,所以在这一侧的话,RP的深度针灸的话是是是很有必要的,对我们这个所有程序员,对于架构上的三方都理解,所以这个课后面肯定这么设计好吧,对周老师没有李老师的嗓子大嗓子这个咳咳。

上岁数上岁数,对他说这个内容有点偏少啊,我给大家解释一下,其实我不是这个,我跟你说啊,这叫大纲,对这个每一个点,然后它背后刚才说你要把它译成是一个拔高的,我刚才说的这个问题就是真的太难了。

同学刚才发了几个疑问,所以说一个一个一个重复的,把之前我们讲过一个录播,然后再给你重新讲一遍,不是这样一个课程,这个标题大,这个课的标题已经看出来,就架构师进阶版是我们一定是讲的是进阶的,提升的对。

有有营养有素质对吧是的,然后重点的话呢就是我们的右手边的曹老师啊,大概讲一下,像这一个就只能听到吧,来来来放近一点,来来来能听到吗,我我站起来站起来可以礼貌礼貌一点,礼貌礼貌一点啊。

那个就是比如这还得蹲着,所以你坐这,你就在这说,那个就是这个三高项目的架构设计课啊,就是呃这是这个我们是安排了,有大概四节课是吧对,然后这四节课呢就是计划把里面的,就是架构设计的重点。

在这里给大家讲清楚,就是从请求进来经过什么节点,然后每个节点该怎么去设计,比如请求进来什么CDNDNSL负载均衡呀,然后缓存呀,消息队列呀,然后后面的数据库,然后中间可能服务之间调用会遇到什么熔断。

降级,限流隔离等等,这些东西呢,都给大家把它就是讲到它最精华的部分,就是让大家嗯知道在实际的企业当中,你只用哪些,因为其实这里面的方案会挺多很多的,就是比如说熔断的方案很多,但是在这里面。

其实一个企业当中基本上只用一种,就可能程序员熟悉这一种,就用这一种,然后我们呢在这里面就会把比较主流的,在呃在这系列课中挑选出来给大家讲啊,就是三高设计课呢主要就这些内容,争取四节课给大家。

把这种主要的设计方案都给大家讲清楚了,你看有同学说给郑老师多拍些歌,郑老师现在都都拍给都拍给他,我们听着的歌,郑老师现在是在做一个痔疮手术,嘴上嘴上起个泡,好好好,OK这个里面的更新它肯定是有的。

因为啊我们的这个课程呢,它其实是基于一板一板的这个优化,然后优化的一个前提,就是要根据现在的市场的一个面试需求,因为我们最近包括我们在座的,包括曹老师也好,周老师也好,每天都要服务比较多的学员。

从我们的服务这些学员,比如说解答问题啊,对不对,然后做这种简历指导啊,或者做这种学习路线的规划,或做这种面试规划或者模拟面试,我们会就是获取一些,比如说包括现在的最新的企业的一些,招聘信息啊。

现在基本上企业招聘的话呢,他会更偏重于你的动手能力啊,就是原来的话可能就是我们常说的面试八股嘛,就是面试的时候,然后问这个原理,问职员们问什么多线程对不对,问锁啊,问一些什么源码之类的。

然后现在卷呢就是说卷的更多的,就是他考验你的动手能力,就是说首先他要验证你以前那个项目,是不是这么干过,就像曹老师说的啊,我做熔断限流对不对,那你说你简历里面你写的熟悉这一块。

那是不是你要把这个你以前公司做这个东西,应该给我讲清楚,这个课里面的计划就是怎么说呢,因为我讲别的项目里面也用到了熔断限流,然后这里面我把那个案例代码都给大家带出来。

到时候大家就是比如说我们讲到熔断限流,然后到时候会告诉大家有什么地方有案例,大家看一眼就会了,这样就我我我刚才看到同学,你像这个叫弹一闪,就问了一个非常有价值的一个问题,前几天变拼多多。

然后问了中间建的高可用方案,这个就符合这个问题,就符合架构进阶班的课程内容,所以就这样吧,咱们今天临时起意啊,这个到时候准备一个一准备一个接口,这个接口你看是定义,我们是准备一个留一个邮箱。

还是留一个什么什么地方,或者一个就让同学能把问题,那就是你这个接口别太复杂了,然后还得经过几手,就最好有一个地方,然后啪啪啪就搬砖了,班主任班主任就是你们找班主任,就像刚才弹一闪,这个问题非常好。

就说哎前几天面皮多,问了中间件的高可用的方案,那这个问题你们就咣咣就发,发的时候呢,我们老师这边,然后所有人扑上去,然后开始梳理这个这个问题会在哪个模块里边,然后这样你们问的多越多。

然后就带大家一块去思考,怎么把这个课可以讲的更有高度讲,讲得更好,而且更贴贴切于十这个时实际这个方面的好吧,所以我们就是咱们之前那个老学员应该知道,就是咱们很多课程都是这种互相打磨着出来的。

只要你咱们同学能积极的反馈对吧,然后我们就一定会把这个这个课程做得更好,因为是更符合你的需求的,对这个说任我行说把面试题收集起来,对面试题的话,我会收集一些比较经典的,对对对,叫技术众筹,叫技术众筹。

我们管这叫技术,不是费用,众筹,是技术众筹,抛出这个问题,或者遇到这种,就是比如面试的时候遇到这种场景啊,对不对,这话可不只不只限于面试的公司里,面试的你在平时蹲厕所的时候,突然想到一个就是坐在马桶上。

突然想到一个事儿,说哎这个这个架构挺有意思啊,说这个怎么做都可以,就是把你这个所有问题抛出来,但但但是啊这个你你们随便随便随便发讲,不讲的是我们的事,这个任我行发了个在职证券,好像也挺容易的。

发一个也可以也可以,这个他也也别,他要他要那种填的形式的在线问卷,如果说他比如抛出问题的话,那肯定就是那种类似于填空题,时间长短,反正就两三天填完,填完再收集一下,比如说收集一下,大家对这个对。

那我记住这件事情,对我记得这件事再推一波这个手,我们再把直播课程再推一波,然后收集过来之后的话,这个就是咱们直播互动的好处,你们多聊多想,咱就好好方法,对不对,对,这个问卷的话,我们是就在对。

反正我们就做一期嘛,就是一个期做一次这个问卷嘛,我不可能天天问,天天问的那个问题,就这样弄,那个咱们网站上,然后单开出一个页面,或者单开出一个链接的,有很多那种共享的VIP,可见他有的是点进去之后。

然后就可以开个第三方的各种问卷,挺好用的,其实在那个问答里面开一列,就提问的时候选一个什么课程,不是最简单,最简单的就是我们可以在这个班的,就是咱们弄一班的班班的,直接就说这个这个线几号到几号之内。

只有VIP学员有权限,然后呢点点我,然后提交你们想听的知识点内容做这么1banner,然后咱们同学在场的,不在场的,有没有看那个视频呢,他找访问咱们网站了,他大概率看到你班长。

然后再加上班主任那边再去推一下这个事,然后我们三五天之内或者三天之内,然后把那个文件这个问卷,然后就就尽量出到更多的学生,把问题收了,我们先做也别一下这个这个收购,收收收收收太多。

毕竟我们要一个能核算一个工作量,比如三天输三天的,拿回来之后,这些问题我们能能处理完,然后能排到后面课里边,这大纲就跟着变了,然后这个事如果发现好的话,我们就比如说每每个月定每个月定一下。

周一号到5号就是收集问题的对吧,咱们这么玩是不是也可以,你觉得可以,同学来敲门,六六啊,可以吗,这么来这么搞,嗯嗯有30万的事,我知道有30秒,30秒对,你看这行,这这这可以这可以对。

就给他弄成一个长期化,对有节奏有节奏的那种,就是希望大家都参与起来对,因为这种直播课程的话,其实就是说如果按照做项目的话,我们是我们还是你们是甲方,你是甲方爸爸,对不对。

然后这刚才是讲的这个三高的架构设计啊,然后我就给大家着重讲一下,比如说今天坐在中间的李老师会给大家讲,所以在这个rock q里面,你也可以看到,我里面更多的是去给大家去讲一些实战相关的。

因为像这种中间件啊,其实面试的时候可能会问到这种,就高考用三高架构嘛,其实除了这种三高架构之外,就是有一些学员他其实有一些痛点,这个痛点就是我可能在这个公司,我压根没有用过它,但是呢我去面试的时候。

我要写上,结果我写上啊,比如说李老师帮你写上了之后,面试官一问结果反正你都答的不顺畅,因为你现在一面试一答的不顺畅啊,是阿八阿八之类的,基本上面试官就会断定你这个没有用过,或者是非常的生疏。

所以这里面的话我会给大家去讲,更多的偏向于实战的,就是你不要看这种实战的话,它其实不是说一定要把这个代码,嗖的一下拿下来,而是说我讲清楚很多的业务场景会怎么去用它,因为像你讲的rock q的话。

其实像rock q卡不卡,那就差不多了,因为MQ的话,这个东西就是说你只要熟精通其中的一种,其实这三种这三种像ruby的,像卡夫卡的话基本上也就差不多熟悉了,除此之外的话呢。

我还要去讲一下像里面的一些原理机制,因为这个消息的存储,消息的确认,然后还有包括他的网络框架啊,所以我会着重去从这几个点,给大家进行一个突破啊,也许大家可能会觉得,中间件这个模块的话还是比较重要。

但是的话呢就是很多小伙伴就是没有发力点,所以这个rock q的实战与原理的话,就更多的会从同学们去面试,或者工作当中的一些发力点来进行出发,然后像这个release的实战与原理啊。

这个release的实战原理的话呢,我列举的点很多,其实这里面呢前面的东西可能会比较浅一点,一些基础运用吗,这里面比较复杂一点的,可能就是b Mac不能过滤器和happy log log啊。

前面的这五种数据类型还是比较通用的,然后底下的话呢,就是涉及到像它的持久化的原理,像他的这种内存淘汰的原理,然后还有包括我们的这个做主从啊,做哨兵啊,做集群啊,以及分布式锁以及缓存一致性的这个方案。

所以在这个课程里面呢,看起来跟我们之前讲的差不多,但是我会把内容适当的拔高,就是拔刀的这个业务场景,也会要和架构设计要挂上一定的关系,就是大家知道就是在你的这个工作当中。

可能就是在你的项目里面会写着release,对不对,但是你要了解这个release你到底用它来干嘛,对不对,有的人我做缓存,那缓存其实有很多的缓存,也可以做e catch的缓存,也可以用MONGODB。

对不对,那你REDIS为什么要用它,然后release这个里面呢,具体的话还会涉及到一些bug,哎我记得周老师之前讲了一个release,早期版本的时候,好像提出了一个,我记得有一个你还记得吗。

一个AOF的一个bug,但是那个bug的话在release7的这个版本已经修复了,我们学员就直接给我们做了一个反馈,这个反馈就是说,诶好前周老师讲的这个release里面的那个演示的bug。

在release7的这个版本里面,他其实已经修复了,就已经没有那么bug了,所以我们讲这些东西的话,尽量的会去讲比较新的版本,因为比较新的版本,你像release啊,就是他新的版本出了多线程嘛。

然后release里面的话它支持了更多的数据类型,所以呢这是我们讲release的一个实战与原理部分啊,同学又反馈了几个问题啊,就是说现在最近面的大厂基本上都没啥罢工了,然后全是实战相关的。

然后算法都基本上是数据结构精讲那些基础的,然后是这样的,弹一闪,今天给的反馈都比较清晰,然后这个而且又有有有细节,这个这种这种方式很好,我想想基于他的说法,也是就是我们既然要做这个文件系统。

然后你们在骑的时候就不要太模棱两可,就比如说那个加一个什么新课,加一个就是两个字,或者一句话,你们稍微说的具体点就是哪方面的,然后呢比如像这个面试官问的相对比较垂直,那这个就是垂直。

可以举个example啊,来个例子,你比如说可能我我因为我遇到了什么什么,他问我哪些问题,这个这个所谓的垂直到底是垂到什么程度了,对吧,然后呢或者你有你对这个这方面有一个什么,想达到什么效果。

老师让老师应该讲到垂直讲到什么程度,你给定一个问题,然后并且给定对这个问题的描述对吧,然后12345,然后这样的话,其实大家平时在公司工作,应该也是这样的一个工作,一个交流方式,就是信息传递的时候。

不能说这个信息是一个模棱两可的,要要稍微精准一些,然后呢减少这个对方对于分辨你信息的时候,这个这个容错或者其他的问题好吧,也就是希望大家能多用点心思,然后呢每个人也不用想太多。

然后呢到最后众人拾柴火焰高,问题一收起来肯定也是很多的对吧,那个牛将军这个同学,我给你回答这个问题啊,开源项目的话,我们其实开源了一个请叫马士兵严选看一看啊。

这个课程的话原来是我们的诶。

我知道他大概说的啥意思,对这个跟那个不是你说的,我知道他是说开源项目都参与嘛,其实那个的话大家可以去参与的。

搜一下吧。

就是其实我们马士兵严选的话,我们现在已经把它拆解的很细了,原来的话呢是一个大的壳,现在的话我们把它拆成了像它的框架,像它的基础基础的一些组件,就是大家知道你说你要去写一个这种。

或者是说站在架构师的角度去封装,一个框架的话,你肯定要去封装像这种什么接口啊,异常啊,然后像这种大家可不要觉得这些东西简单啊,其实你要动手写的话,你可能没有思路,没有头绪,比如说日期时间的管理啊。

然后一些基础的统一组件啊,一些工具类的封装,这个你应该说的就是这些东西,就是你如果说你真的要去参与编写,开源项目的话,他一定要具体到某个点啊,你不能说你参与了开源项目,然后面试官问你参与了哪个。

我参与了架构设计,那设计的哪个,你跟我细一下,你是设计了它的统一的什么接口响应,还是统一的异常处理,对不对,或者是统一的一个组件,所以说这个课的话应该是可以满足你,包括里面一些实用的东西。

你看使用的东西的话,这个地方其实就是对于一些我们常用的注解,开源架构进行修改,嗯啊就是你说的所谓的,在有些部门叫做组件开发部门,他干的活就是说我对这个组件进行增强啊,我们使用一个统一的缓存组件啊。

这个地方你的细节不用管了,拿数据的话,缓缓存帮你有对应的set方法,有对应的get方法去处理就行了,对不对,然后你比如说那个接口做限流,我们统一的限流方式,然后封装的统一。

封装的就是能够满足日常用的这种限流算法,所以这个就是刚才那个刘将军啊,就是你说的问题,我给你进行了当场的答复,好接着继续刚才说到的。

这是release啊,按release的话呢,我们之前是讲过,我记得讲过一把源码嘛,其实包括我后面讲这个release,我也涉及到了这个嘛,藏一下这个吗,对对对,好好好对对对对对对好。

就是刚才的这一个圆嗯,REDIS里面呢为什么讲到他的一些源码呢,就是因为像这种基础的数据结构,我发现在最近的去年到今年,很多面试官他喜欢问一些数据结构的源码啊,他不是问你什么这个地方的整个流程的源码。

因为大家知道release是C语言写的,他不可能问流程,他就问你像string它的底层的源码是怎么实现的,像它的list的hash sz,sat这种五大基础数据类型啊,因为REDIS为什么说非常好用。

或者rise为什么说经典,它主要是它的设计在每一种数据结构底下,他都用了至少两种以上的实现啊,所以以后你就记住这个点,就是你看到的这个string hash list set,在它的底层。

它至少有两种结构啊,这两种结构一般是适用于不同的业务场景,就是有的可能是数据字段比较长,那我可能用这种,有的呢可能比较短,我用另外一种就是站在这个存储啊,站在这个算法的角度来说,它是最优的好。

那么刚才呢我给大家讲的,就是我们整个大纲的这几个部分啊,卡住了还是怎么,他说老老乡民扛不扛不住。

每天都得都得上上个香,对很虔诚的,然后这个部分的话,我们进入第三个部分吧,我们大纲其实也介绍清楚了,就是大纲的这个十个部分啊,形式互动对我们讲究的是互动形式,然后因为我们今天是一个开班仪式。

所以在这个开盘仪式呢,我们会给大家去分享一些,就是老师自己的一些学习技巧,那么在我右手边的这个曹老师可以说一说啊,首先我回答一下这个任务新的问题啊,这个用到我们项目里不用付费吧,自愿的啊,我们不收费啊。

目前是不收费的啊,对对你来了没有,那个下下一个是啥,分享学习技巧是吧,嗯大家可能问到学习上最多的问题,就是这个东西学了很长时间过后之后就忘了,可能比如说学了个JVM调优,过了一个月可能要到面试的时候。

确实是真忘了是吧,你也不仅你忘了,我也忘了,然后这个这个问题怎么办呢,其实就是我就是辅导了这么多学生的面试,然后给他们的建议呢就是一个学了一个知识点,然后呢比如说嗯比如说限流吧,举个例子啊限流。

然后你做好那种在JITTER里做好一个压,就是那个压测的那个thread group,做好一个这个,然后呢写好一段,写好一个测试限流的代码,OK这个把它打包在那个git上打个tag存好了。

你这次看看懂了,你下次再来看的时候,把它就是把这个tag这个代码牵出来,然后再跑一遍,然后简单看一看,你马上就能回顾起来了,然后这里面反正就是写那个代码的时候,写的详细一些。

然后基本上你好踏踏实实学过一遍,最后再来看一眼,基本上就会嗯,还有一个就是那个,经常尝试着给自己买一个东西,讲清楚,像我们做老师啊,有的有的时候其实我们呃看书,或者说看官方网站。

可能这个东西就是我们作为老师,可能觉得我们懂了,其实就是我们觉得自己懂了之后,和给你们讲道讲清楚,其实这中间差别还挺大的,不一定说我觉得我看懂了就能给你讲清楚,其实中间确实比如说表达的时候有时候不流畅。

或者说不是那么有条理,或者说不是那么的全面,讲到可能到后面的时候想起前面某一些点忘了,其实我们我们平时也会在内心去模拟很多这些,所以呢就是能给大家一些建议呢,就是大家平时比如说学了一个点之后。

也尝试着是吧,给自己的女朋友讲清楚,比如说左老师算法讲的那么好,为啥是吧,天天在家给老婆讲算法是吧,你们能你们要这么做到了是吧,也挺牛逼的,好话筒给到林老师啊,我给大家说一下,其实像学习技巧这一块的话。

刚才有同学提了很多这种学习方法论嘛,嗯我给大家举一个比较通俗的例子,就是一般在企业里面,就是你做项目的时候,其实运用的技术啊,它不会像我们大纲全用上,你不可能说一个就是如果全用上的话呢。

那基本上都是大厂的架构,但是在大厂架构里面呢,你如果不是这种大厂架构师,基本上你可能是负责一个模块啊,我可能是负责订单,我可能负责支付,我可能是负责商品,对不对,然后在这里面我强调一点。

就是说你像我们展示了这些东西,它就有点像我们平时所说的,你说24节气,那听到说到什么什么清明,还有什么秋分,对不对,可能你听到一两个词,你能够冒出来,但如果面试官问你,你给我说一说24节气大概有哪些。

我估计90%的人是背不出十个的啊,这个区别点在于哪里呢,就是你这项这项知识的话,如果你经常用或者是经常敲或者是经常做的话,或者哪怕做一下笔记,或者做一下命令,或者敲一下代码的话。

他可以做到一个温故而知新,所以我我给大家的一个学习技巧,就是在于你学这块知识的时候,首先的话要多动手,就是你动手首先要敲出来,你像我讲release开始都是去讲命令,讲五大基础类类型的命令。

为什么要讲这些东西呢,以后你用到的可能是JS,用到的是REDITION或者是release template这种东东,但是其实这些东西你命令熟悉的话,你看它的API接口,你一眼就明白了。

所以以后你在工作当中你把命令敲除了,你会发现你用API的时候很爽,诶,这个地方我要用哈,希对不对,那就是一个对应的对应的一个API就出来了,然后I第一弹对不对,但是如果你命令不熟。

那这个地方他怎么会有两三个参数啊,怎么送啊,对不对,然后这个命令,它这个操作的命令到底有什么区别啊,对不对,所以这是我给大家分享的一个技巧,就是你一定要在几个大的主要技术里面,要多花些心思。

就是你要多投入一些时间,可能老师在给你讲的话,可能是讲把这个命令快速的给你一两节课,敲完了,对不对,然后具体的知识点,这个时候你要去自己在工作当中也好,或者是你工作当中有时间是最好的。

或者是说你学习的时间好多去敲,然后敲完之后的话,其实你去面试的时候,你就压根不慌了,你跟面试官讲的时候,这些东西你没那么容易忘啊,很多人就是说容易忘的一个点,就是我只看就是有一句话叫什么。

甚至叫我收藏收藏我就学会了,我们称之为学费啊,那就叫学废了,OK啊,这是我给大家讲的一个学习的技巧,然后我我我帮大家分享一个。

就是一个比较理性的一个东西,就是学东西,这个大家说学记不住也好,或者这其实都是一个借口,为什么,因为你就没有用心思,就是如果你喜欢一个女孩,尤其你的初恋,我也是哈哈哈哈哈,太多了。

不是就是如果你像你的初恋是会记一辈子,就是你看你用心的程度,然后呢这个你你初恋为什么可以记一辈子,因为你记住了他很多的细节,比如说他哪儿好,哪儿温柔,然后你能说出五六十个来对吧,或者七八十个。

但是比别的女孩子,你就说出来很少注意听,刚才那个就是就是本质,如果你想把东西学好,学东西的过程当中,就一定要关注这个东西的方方面面,也不要这个一平板大屏的逛逛,或者是死记硬背背一些调理的东西。

这是不对的,有任何的一个技术里边的,任何的某每每一句定义,你要去展开它,然后但是这种写法呢,你初听上去就好像说每一个东西我学的很细,很细腻,比如说一个我就像连连连老师讲了一个spring。

他要讲70个小时,然后你听他的课,听70小时,我是不是还得画出来啊,200小时,然后再去钻研它里面每一句话,然后这这就是错误的,我教你一个正确的学习方式,就是第一个是先宽什么,先宽,你先呃不要让自己说。

每一个看课我都要达到老师那个程度,或者学得很很很很好,先快速过课,先打开自己的认知,因为有一些东西就是呃咱们举举举例子啊,把知识分成两类,一类知识很死板,很刻板的,比如说像if else循环哎。

另外一类它就属于我们这个编程,逻辑思维的东西,逻辑思维的东西它就是很很很泛,但是他又有很很有规律的,你必须打开视野,我就举个例子啊,就比如说咱们讲呃MQ啊,或者讲我讲大数据的时候。

讲所有的找凡是涉及到这种通信的RPC的,然后等它都会有自己的这个command,然后就抽象的过程,然后呢都会有命令的这个匹配的,适配的和DDD拍摄的过程,那这个时候其实当我看第一次看的时候。

比如我第一次看到spark啊,我见过这种形式了啊,他以这种形式展现出来了,后边我去讲这个卡不卡诶,又见到他以另外一种形式展示了,但是大差不差,他的逻辑框架已经出现了,然后我再去讲这个诶。

还是我就我就你再去看任何没Q的时候,你就会发现我不是要去看,我是要带着前面那个东西,我去论验证和论证这个东西,所以你只有你的认知,或者你多看课,先看,看完之后,然后就等于一个课程。

比如说全算下来是400个小时,你要先用11。5倍或两倍速度,先给他突突了一遍,突完之后,然后再翻回头去,然后呢再涂了一遍,就是你拖个两三遍,这个课程它比你说每一节课按在这两个小时,我要拿出三四个小时。

研究这两个小时到底讲什么东西,它要更更有效果,再举个例子,你们自身的一个一个感觉,就是这个我听了A老师的,比如说REDIS听完之后啊,然后还还行,我去听了毕老师的REDIS。

我看这毕老师讲师讲的特别的好,我可以跟你说,未必是这个B老师讲的特别的好,是因为你前面先听了一遍,在听毕老师的时候,你在已经有认知的情况下再去接收一遍的时候,你的条件反射就有了,你又共鸣了。

你就知道他这个前后的关系,你你就能适配这个东西了,所以学习啊就是不要只学一遍,而且是那种特别死板,特别细的学,你要尽量的啊这个课都快速过过个两三遍,然后呢第一遍裤子过的时候呢,也不要只过。

然后呢你要随手留个纸和笔,永远记住,昨天我讲课的时候说这事儿了,不要相信自己脑子,你脑子会欺骗你的啊,就是我我我我学会了,我听懂了,我理解了,我记住了,这全都是假的,都是假象,你又在纸上去写写大纲。

写他的这个拓扑,然后你要抓的是这个脉络,第一遍,第二遍的时候,然后再基于这个脉络里边,你要敲重点,然后呢圈这个突然的那种条件反射哦,原来老师刚才那那那那那那课讲了这么一点,我没有get到。

或者原来原来前后前后的课程111,这个后边的东西为前面一铺垫,原来真的是这回事,你只有这么去学,然后东西就很难去,就是绝对的忘记它,让你的复习也会变得非常的快,而且这个才可以满足香港的老巢说的说。

你如何给你的女朋友,给你媳妇,或者给你的朋友同事讲清楚,就是这种费曼学习法,就是你自己这一关要过了,你如果自己在学东西的时候,嗯是一种就是这种这种应付式的学习,就是我就这个这个使劲嘎学。

你很难去给别人讲讲的,因为你没有没有没有这个拳击的概念,你给别人输出的时候,就跟大家说,我要说一个事,但这事我还没想好呢,我要跟你开始说,那这个收起来肯定很复杂,但是这个事儿我自个儿心里想了好多遍了。

我也预言了好多遍了,那这是我在跟别人聊的时候,我一定总分总的我现在跟你说一个事儿,这事儿大概是一个什么事,然后具体会有几个点,然后之后几个点分别是什么东西,就是你最后你要让你的知识灌到你脑子里边。

你能总结归纳的能力,比如我说我跟别人聊release release,大概的跟你说啪啪啪啪有几个点,对不对,他的单机这方面呢,他在自己内部数据结构的,在于它的这个这个性能优化的,在于它的持久化可靠性的。

然后再说的多机这方面在于集群方面的,把你有一个逻辑性条理性给他说出来,但是这个东西你说我随着课程慢慢学的话,你很难去在脑子里建立这种这种感觉,你没有感觉,只有你先快速突了一遍课哦。

老师总共就说这么多东西,我又回去看了一遍,验证了他说的他这个思路,逻辑思路在这,其实有的时候你们学一个课的时候,第一你只学了一遍,你是不知道老师,因为一个课每个老师讲法是不一样的。

就REDIS李老师和我讲讲法绝对不一样,但是我们都会我们自己的逻辑在里边,你听一遍,你是很难最后能悟出了我们的思维逻辑,我们是在偏向于哪个点上去讲这个课,你只有快速爬过一遍,然后知道先先找这个点。

你回去再过一遍的时候,你就特别能感感悟到哦,这个老师可能是偏他的这个里边的架构的,这个老师可能偏源码的那个老师,可能偏它里边这个经验优化的等等,好吧,我们就利大家说这么多。

就是希望大家能在学习的时候能驾驭这件事情。

系列 5:P10:10、程序真的是按照“顺序”执行的吗? - 马士兵学堂 - BV1E34y1w773

一般来说呢关111谈到多线程的时候。

一谈到并发编程的时候,我们都会讨论它的常见的三个特性,这三个特性这三个特性呢分别叫做可见性。

有序性以及原子性。

这里面最简单的实际上是可见性。

就是多个线程之间改一个数据之后呢,另外一个线程要及时可见。

这一般来说我们拿过拿volatile修饰一下就可以,第二个呢就是有序性。

有序性稍微复杂一些,原子性是最复杂的,这里面牵扯到各种各样的啊五花八门的。

甚至给你开放了,你可以自己往里填的五光十色的锁lock是吧。

呃今天呢我们聊这个有序性这件事,我们先从一个有意思的地方聊起,就是程序真的是按顺序执行吗,有同学说老师你在这逗我玩呢,那个那难道程序还不是按顺序执行呢,当我们看到两句话的时候,比如说X等于X加加。

这是你的程序的写法,一定是先写的先执行吗,X等于先执行,然后X加加再执行,X变成二,不可能X加加先执行,那样的话,那编译都会没准都报错是吧,所以程序当然是按照顺序执行了,但是未必,比如说像这两句话。

X等于一,Y等于一,你说这哥俩谁先执行,对最后的结果有影响吗,没什么太大影响,所以程序真的是按照顺序执行的吗,来我们来看看小程序就行好,大家看这里啊。

呃这个小程序是非常经典的一个小程序。

这个小程序最早开始的时候是拿C语言写的。

呃,关于这个小程序呢,我简单给大家解释,你认真听。

需要一点点小小的业务逻辑知识,逻辑知识,不能说业务逻辑逻辑知识。

数学的推理相当的简单啊,你看我这里面有四个值。

XY是一对,AB是一对啊,可以说是有四个值两对。

那么在这四个值里面呢,我做了一个循环。

这个循环的不停的循环,每个循环里头我都会起两个线程。

这是第一个thread,这是第二个thread,这两个线程干的事特别简单。

第一个干的事呢就是A等于一,X等于B。

第二件事呢叫B等于一,Y等于A哇,太简单了,不能再简单了。

好我们主要分析的是什么呢,主要分析的是当这两个线程结束的时候。

Let await,然后最后我们两个拆线程都结束的时候。

我们最后的这个X值等于几。

Y值等于几,再说一遍,这是我们第一个线程A等于一。

X等于B,第二个线程B等于一,Y等于A。

由于他们两个是位于不同的线程,所以它们之间有可能交叉执行。

交叉执行之后,我们X等于几,Y等于几。

这是我们需要探究的话题,大家听懂这个问题了吗。

能听懂的,给老师扣个一,嗯嗯嗯搞点反馈啊,Hello,幻雨星辰嗯,都是活人,对不对。

太难了,嗯这是一个证明题。

不是让你从头到尾设计的,你能听懂就行好吧,四种可能啊,胡服你看胡服多牛多牛叉,他居然分析出了四种可能啊,哪那么多可能啊。

我们来分析一下好不好,好大家看这里啊,呃既然是两个线程,我们假设这是第一个线程,这是第一个,这是第二个,这两个线程啊,由于它又会交叉执行,所以说不准是哪条语句先执行哪条语句后执行,正常的情况下。

比如说像这种情况,A等于一,X等于B先执行,然后B等于一,Y等于A后执行,那么这种情况我们分析一下,这时候X等于几呢,X等于零嘛,因为B初始值为零嘛,对不对,所以X等于零,Y等于几呢。

由于A已经设为一了,所以Y等于一,所以这种情况叫X等于零,Y等于一,或者是什么呢,第二个线程先执行B等于一,Y等于A先执行完了第一个线程才执行,A等于一,X等于B那最后的结果就是X等于一,Y等于零。

哎超级简单,那剩下的呢就是各种各样的排列组合了,比如说我第一个线程先执行依据,第二个线程执行依据,第一个线程又执行第二句,第二线程又执行最后一句好,这种情况是X等于一,Y等于一好,第二个线程先执行依据。

第一个又执行,第二个线程又执行第一个右执行,总而言之,这样执行完好,X等于Y等于一,如果说第一个线程执行完一句,第二个线程执行两句,最后第一个线程在执行一句,X等于一,Y等于一,如果发生这种情况。

第二个线程先执行一句,第一个线程两句,第二个线程又回来,X等于Y等于一,Ok,这就是我们分析出来的所有的排列组合的结果,这块你没有跟上,关系也不大,我呢就跟你已经分析完了,反正总而言之就是这三种结果。

哪三种分别是X等于零,Y等于一,X等于一,Y等于一和X等于一,Y等于零,来我们来跑一下,看看他最后的结果到底长啥样,run见证奇迹的时刻好。

这程序由于是个特别长的循环,不停的循环。

什么时候这个循环才会退出呢,只有是发生X等于零,Y等于零的情况。

他才会退出,他会给你打印出来,说第二次的情况下发生了X等于零。

Y等于零,这种情况。

这个需要看,人品的啊。

看运气的,看看石子的人品到底好不好。

如果好的话,我们很快能见到这个结果,如果不好的话,我们今天晚上估计够呛了。

没事,明明周末是吧行你们想得开就行。

不会吧,真不给面子哈哈。

听我说啊,就算是嗯就算是没有发生这种情况,我给你把我以前跑的那个截图,给你揪出来就行了,这是我以前曾经跑过的两个截图,第27万,272次循环的时候发生过零零,这个大概跑了得有半小时。

第11问万次的时候发生过零零嗯,Ok very good bingo。

很给面子啊,说明石子石子同学人品不错。

第41万1206次的时候。

发生了X等于零,Y等于零的情况,我勒个去。

啊我讲到这。

你们还能跟上吗,有问题的直接问,没问题,给老师扣一。

嗯哼哼哼。

很好很好,好那现在问题又来了。

这这这这是为什么呢,这玩意不可能啊。

因为我们分析来分析去,你不是发现了吗,只有三种情况,X等于Y等于X等于Y等于一和X,一等于等于一,Y等于零,不可能啊,没有这种X等于零,Y等于零的情况啊,你看你看鹿鹿晗都来了,鹿晗是我们的VIP是吧。

嗯好大家看这里同学问你,我们来分析一下,只有在什么情况下才会发生X等于零,Y等于零呀,注意看只有在这种情况下,首先执行的是X等于B,再执行Y等于A或者先执行Y等于A,再执行X等于B,然后A等于一。

B等于一,放到后面去执行的时候,他才最后的结果才是X等于零,Y等于零,所以通过这个结果来倒推的话,你会发现,看这里你会发现这两句话换了顺序了。

这句话要换到这句话前面去。

这句话要换到这句话前面去,只有在这种情况下才会发生。

X等于零,Y等于零,好讲到这还能跟上的老师扣个一,那说明什么。

说明我们平时看到的这两句话的执行顺序。

并不是我们想象中的,先执行这个再执行这个NO不一定。

也就是说我们回过头来再来看。

我们最初始最最开始的时候这个问题啊,程序真的是按照顺序执行的吗是吗,现在告诉我是还是不是,当然不是好,那现在问题就来了,为什么会发生这种情形啊,为什么他会乱序执行呢。

系列 5:P11:11、为什么乱序? - 马士兵学堂 - BV1E34y1w773

简单说就是为了提高效率,有同学说what乱序执行居然是为了提高效率,没错,举个最简单的例子,大家都知道CPU的嗯,严格来讲应该叫CPU内部的寄存器的速度,寄存器的速度啊,访问寄存器的速度。

就是我们CPU计算单元访问寄存器的速度,要比计算单元访问内存的速度要快得多得多,快多少呢,大概是100比一,比如寄存器的速度是内存速度的100倍,那么假如说我们有两条指令,第一条指令啊。

它是跑到内存里面去读数据,但是由于我的ALU我的计算单元访问,我们计算这个这个这个内存的速度呢,它非常非常的慢啊,我发一条指令过去,然后等着这个内存给我返回回来,数据的时候大概得得有99个时间周期。

那如果后面还有一条指令,这条指令的话呢,它是不需要访问内存的,它只需要在本地的寄存器做计算,比如说对某个寄存器ENX加了一个班好,我就直接在本地做一个计算就可以,我有必要等着这99个时钟周期返回吗。

如果前后的指令没有依赖关系的话,完全有可能是在第一条指令执行的过程中,第二条指令优先执行完,这样的话效率反而是最高的,如果你还听不懂,我给你举个生活中的例子,比如说你要烧开水泡茶,正常的情况下。

你按照顺序执行,是洗水壶,烧开水,烧上洗,洗大壶,洗茶杯,拿茶叶泡茶,但是完完全全可以并行执行,怎么执行呢,洗水洗完水壶之后,烧开水的过程之中,我就直接洗茶壶,洗茶杯,等烧完开水之后,拿茶叶泡茶。

好能get到这一点的同学,老师扣个一,人是有灌鸡汤,有点学不动,灌鸡汤不用我灌,找那个我们的看看看我们最近就业的信息,你不就直接给关了吗,学的动的都已经薪水翻了倍了,它不香吗,嗯好我讲到这儿了。

总有同学也会有疑问,回答同学们的一点点的疑问,哎,几分钟EDD问呢,单核CPU会乱序吗,废话说的就是单核CPU,这跟多核有半毛钱关系吗,单核CPU现在执行的是两条指令的歌,后面这条指令有可能跑前面去。

发生几率小,一旦发生了还会对程序有影响,总感觉弊大于利,上官元恒这里省了99个等待的时间,你居然说弊大于利,你是脑袋进水了吗,发生几率小,发生的几率非常高,我们这个程序为什么发生的几率小啊。

难道你理解理解不了吗,我讲到这还能跟上吗,我下面给你讲,为什么这个程序发生的几率比较小,底层发生的几率超级高,这个程序是一个证明程序,它发生的几率相对小的原因是什么呀。

每一句话翻译到汇编都是好几条汇编指令。

这句话也是要发生这种几率的情况下。

得把这好几条跑到这好几条前面去,当然它就会几率小一些。

与此同时,这两个线程同时发生,这个线程X等于B跑。

前面这个线程Y等于A也得也得跑前面大哥。

这是一个成方关系。

学过概率,这里的发生几率小,指的是那个我们证明程序里头。

并不是只说的底层的发生概率小,这个是必然发生的,那这样业务代码不都很危险,你写的业务代码很危险,你要是理解了,你写业务代码就不会威胁发起执行,还是按照顺序后面执行,先执行,结束,没看懂,请说人话好听。

我说我讲到这呢,很多同学应该能理解了,为什么有可能会产生乱序呢,就是为了提高效率啊,就是为了在前面等待的时候好,后面的呢可以留下来执行,那现在现现在问题就来了,就说什么情况下我们讨论一下啊。

就说什么情况下能够提,能够呃呃乱乱序来执行呢。

系列 5:P12:12、乱序存在的条件 - 马士兵学堂 - BV1E34y1w773

什么情况下好听,我说这种情况呢叫做一条原则,这个原则呢是这样的,前后的指令一定不存在依赖关系,你不能说前面指令是X等于一,后面X加加存在依赖关系,绝对不可能换顺序,但是最终的顶顶级的原则。

这条原则叫做as if serial,来这个单词应该都见过,This is zero,看上去像序列化的好,请给我记住这条原则,这条原则叫做不影响单线程的最终一致性,什么意思,X等于一,Y等于A嗯。

好就这么说吧,无所谓啊,这两条指令先执行后执行,在我这个县城里面,影响最后XY的结果吗,ab的结果不影响啊,这俩这哥俩谁限制性都可以好,这就是乱序的最根本的条件,就是只要是不影响单线程的最终一致性。

那么你就可以做到整个程序看上去像序列化,实际当中有可能是乱序的,好了,这个东西叫做as if serial,看上去像序列化的,但实际当中是乱序的,只要是单线程的最终一致性不受影响,没关系。

里边的顺序随便换,这单词见过对吧,那个最近有同学说我们讲课的问题啊,嗯好像是最近啊。

A1周VIP啊,嗯上了一周课,就上了一周的课,上个月看java并发编程的艺术,还有深深入理解java虚拟机,完全一头雾水啊,学完课程全都懂了,对你们自己看看,基本上听不懂啊,嗯嗯咋说呢。

你们如果看到这个单词a serial,估计很多同学也理解不了到底什么意思,现在大家伙应该都能理解了,就是很简单,因为我们CPU需要提高效率,所以他最终有可能乱序执行,乱序的最终的原则就是。

只要不影响单线程的最终一致性,可是他现在影响的是,不影响的是单线程的最终一致性,但是我想问你的是,如果多线程会不会出问题啊,多线程会不会出问题,当然会啊,你看我给你举的这个例子不就出问题吗,X等于零。

Y等于零,是你期望想得到结果吗,未必,但是它就出现了,当然这种问题呢是存在于面试里头,我再给你看一个问题,这个问题看大家能不能找得出来,当你理解了乱序这件事之后,我们来看这个问题,来看这里来。

我先跟大家说啊,嗯这个问题是出自于一本书,这本书叫ja and currency practice,那本书你从头到尾看,你也看不懂,听老师讲你就能听懂了,这个小程序是降子底,小程序呢有两个值,第一个类。

第一个值是布尔类型的ready,第二个值是number,ready等于false number,它的一个初始初始的默认值就是零是吧,我们有一个线程reader thread。

它执行的时候是我not already,只要你这个还没有准备好的时候,Not already thread yield,我的线程就不执行,继续下一次循环,什么时候你好了,我就把那个给你打印出来好。

我们的主线程干了一件事,让这个线程启动,把number给它设好,number等42诶,设好了,设到number里,然后把ready等于true,那我们这个值就已经打印出来了,最后呢我们等这个线程结束好。

我想问你是不是我们打印的这个number值,一定就是期望我们这个42期望的是42,是这样的吗,另外仔细阅读这个小程序,给我挑出来这个程序中的两大毛病,两个大毛病,给大家30秒时间,读一下啊。

这小程序有两个大毛病,30秒钟,看警方问了个问题啊,说那个其他高级语言也会有类似情况吗,听我说所有语言都一样,今天我讲的内容跟语言没有半毛钱关系,我现在讲很多东西都跟语言没关系,我讲了rust语言。

讲过go语言,讲了N多N多的语言,我们的课程包里都包含这些语言,但是你理解了一门,其他门呢理解起来就非常的简单,罗哥哥说join join是个什么鬼,这小程序已执行结果是对的,你执行1万遍。

这个结果都有可能是对的,单手我直接告诉你啊,就变成如果按变式来讲,它有两大毛病,米兰的老铁匠不是ta run吗,老铁匠同学呢是一个零基础的小伙伴啊,你非常的可爱,其实你比较面的时候最好不要说话。

因为你说话容易让别人知道你比较面,先从我们零基础的课开始慢慢跟,好不好,老铁匠,95kg嗯好我们说问题出在哪,这里面有两大问题,第一大问题是呃,这个线程很可能结束不了,什么意思呢。

就这个线程呢有可能结束不了,这里面说的是线程的可见性问题,可见性说的什么,这里有一个ready吗,ready是在我们内存里false,然后我的主线程main线程,我把这个false给改成了。

我把这个RAR给改成了true,它是改的哪部分内容,实际上改的是他本地的缓存,改的是这部分,把自己缓存的这个给改成了true,所以如果这哥俩不做同步的话,而另外一个线程我们的reader thread。

他读的是自己本地缓存的这个R它是false好,如果这哥仨之间不做同步,我告诉你这个县城有可能都不结束,当然由于线程可见性,它底层的内容呢牵扯的比较多啊,MES是一个主动机制,它就有可能给你做了同步了。

像那个volatile是一个被动机制啊,就是lock指令帮你做的,这个呢今天就不聊就不聊了,反正总而言之,如果你想让这个程序写的比较严谨的话,这里要加一个关键词叫volatile,还有这是第一个问题。

如果这个问题没听懂,放一边,我们讲有序性,主要聊的是第二个问题,这个问题是什么呢,这个问题就在于同学们,你们想一下,如果说这两句话发生了顺序,再看一遍,仔细分析一下,如果这两句话发生了,换了换了顺序。

ready等true等于42放到前面去了,我们正常的情况下不都是这么写吗,我先把这number改成42,然后再把ready设为true,正常应该就打印42了,不一定的。

如果ready等true在我们执行的时候被放到了前面,跑前面去了,那么这时候ready就先设为true,也就是说这块就先结束了,打印的这个还没有来得及来得及设计,42的时候,打印出来就是零,好。

能get到这一点的同学老师扣个一,所以这个程序不单单是有那个可见性问题,还有还有什么有序性问题好吧,这种情况有办法解决吗,当然有,Sure,必须有,这种情况解决的最优雅的方式,你们可能都想不到。

叫做atomic preference,当然还有其他的解决方案,比方说加synchronized,加入entry lock,这些都可以啊,但是最优雅的方案其实是这个atomic reference。

把这两个值设为我们一个引用类型的,一个一个一个成员变量,然后呢设好了之后,统一性设好之后再开始执行啊,这个就不展开说了,我们继续说有序性的问题啊,如果说这个面试题还算是相对简单的话。

那么下面这道面试题就比较难了,看这道题啊,我们来看这道题,这道题我得给他恢复一下原型好,大家看这里啊,New thread,This number,好看看这个小程序哎这小程序特别好玩。

小程序呢就是我我有一个类,这个类里面有成员变量等于八,然后我构造这个构构构造,我们写我们构造方法的时候,直接new了一个thread让他启动,就是说构造构造完成之后呢,我就new了一个thread。

让他启动打印我们这number的值,当然这个打印呢你其实可以理解为,我就是开始使用这个number的值啊,比方说他让他加加呃,让他跟其他的数值做计算,那么我想问你的是这个小程序有没有毛病,这块比较难。

我先说答案,这个是著名的this1出问题,这个是绝对有毛病的,有毛病,有同学说我这么简单的程序居然也有毛病,没错是的,你说的很对,为什么会有毛病呢,好好听我说毛病出在哪,要理解这个东西。

有毛病这件事你得理解另外一个东西好,现在还能跟上吗,同学们,我现在有点把控不好,你们每个人的这种对这种这种这种基础啊,还有同学跟不上还能跟上吗,没问题吧,可以是可以,我们继续啊,还行。

OK这个小程序怎么会有毛病,他毛病出在哪呢,好仔细听我说,为了讲清楚这个问题,我们必须得弄明白一件事,就是我们new一个对象的时候,就是new一个对象,new谁呢,new这个T03。

this escape啊,new这个对象的时候,你有一个对象的时候,他背后到底发生了什么,为了弄明白这件事,我们写了一个特别复杂的小程序,这个小程序太复杂了,看大家能不能读懂好,这个小程序,就一句话。

object o等于new object,这个世界上最复杂的程序,美团曾经围围围绕这句话,提出了九个系列性的问题,答出来,你的年薪就大概在50万左右了,好听,我说我们先说其中一个比较简单的这句话呢。

它背后到底执行了什么操作,什么意思,大家都知道啊,这个我们高级语言,这是我们的高级语言,他翻译翻译翻译总要翻译成为第一级语言,翻译成汇编,java呢又是一个java虚拟机。

JVM虚拟机就把它当成一台虚拟机器,它有它自己的汇编语言,这个汇编语言就是我们的二进制字节码,叫bite code,好下面我们就来看一眼,当这句话执行的时候,它会翻译成为多少句二进制的字节码。

嗯distance说算了,还是去学C加加吗,现在去学C加加的全是傻帽,多说两句吧,有一门语言,那叫Rest,如果你有希望有机会的话,我希望你好好学学,当然我们课程里就已经包含了啊。

Rust rust rust rust rust rust。

rust在哪来着,好像就在我们课程包里啊。

嗯rust语言呃。

这个呢我讲过了,大家听我说啊,嗯可以这么说,现在世界上有很多很多的语言都在抢呃,有一门语言的这种市场占有率,这门可怜的语言就是C加加,好多好多的语言都在抢它的市场占有率,那么有谁呢。

有著名的go on是吧,有最新的Rest,当然还有和rust其他类似的各种各样的语言,原来还有java是吧,哈尔听我说C加加呢,由于它太复杂,当然一时半会儿呢,它的市场占有率也不会被占完,原因是什么。

他以前开发的很多类库太多了,大家用的顺手了,但是我觉得大概未来几十年内,他慢慢的不能说淡出历史舞台,但是他以他的占有率会依然会缓慢的下降,毛病出在哪儿,毛病出在C加加比较复杂,他要手工管理内存。

当然它比较好,它效率比较高,效率比较高呃,他要手工管理内存,但是如果有一门语言,如果有一门语言是什么样的呢,不需要手工管理内存,执行效率跟CC加加一样高啊,跟汇编差不多,那么你说它的市场会不会被抢到呢。

有人长得跟你一样漂亮,还比较便宜,还比较能干,你说你的市场会不会被侵占,好,这门语言叫rust,你们一定要抬头看世界啊,别闷着头往前冲,傻了吧唧的那个路都已经走歪了,还还在闷着头往前冲呢,别这样啊。

好了不废话了,我们来看这个啊,就是你跟着老师走呢,你就永远站在世界的最前沿,it界的最前沿,好大家看这里啊,包括我们讲的service mesh,很多人都没有讲呢,我们都已经开始落地了,就是总而言之。

这么多大厂的一线大厂的老师肯定不能便宜了,他们是吧,得让他们多多的好好的呵呵,压榨他们的价值,都让他们讲课,嗯你呢正好就得到了最好的训练,好看这里object o等于new object呃。

这句话呢它翻译成字节码会有好几条指令,View should bite code with class library,这是一个小的插件,直接拿来用就可以好,我们找到methods两个方法。

一个是构造方法,一个是main方法,main方法点code我们就得到了哦,原来在这里它有这么多条指令构成,好这么多条,看一眼,一共有五条指令构成,12345,第一条指令叫new。

第二条指令叫duplicate,第三条那叫invoke special,第四个叫a store,第五叫return,好,为了让大家能理解这五句话,我专门做了一个,PPT这五句话呢不太容易理解啊。

你认真听呃,这个呢跟我在JVM课里讲过那个class漏到内存,有一个中间态跟这个差不多有点类似,看大家看这里啊,嗯我们假设有这么一个类class t,它有成员变量int m等于8T,小T等于6T。

当我们执行这句话的时候,刚才我们看到了它有五条汇编指令构成,第一条叫new,第二条指令叫duplicate,我们先把它略过这块,我要给你讲的话比较复杂,我得给你讲那个呃县城本地站啊,栈顶指针啊。

怎么压榨,怎么出战,太复杂,扔扔一边,而且跟咱们现在讲的乱序没关系,先扔一边好,接下来invoke special调用特殊的方法,invoke调用special,特殊调用特殊的方法,什么方法呀。

initialize调用它的构造方法好,下面这条叫door store的,意思叫做,把这个小的局部变量,和我们new出来的对象建立关联,它指向一个new出来的对象,所以当我们执行这句话的时候。

return先不管他一共执行了三条最主要的指令,第一条叫new new是什么意思,申请空间,把这块内存申请下来,相当于C加加里面的new,相当于C语言里面的memory allocation。

好第二条呢叫做调用构造方法,第三条叫建立关联,那么这几条指令执行的过程是什么样子的,仔细看,当我们执行到第一条指令new的时候,它真正的会在内存里面申请出一块空间来,这块空间就是我们new出来的T对象。

当然就是一个T对象里面,由于他的有一个成员变量小M的歌,所以这个它里面一定要有一个小M的好,这个小M的值是几呢,在java语言里面,当我们new一个对象来的时候,里面的成员变量都有一个默认值。

这个默认值int类型的默认值是零,很多同学可能没想明白,我说老师他为什么有一个默认值呀,他没有值不行吗,我反正申请了这块内存,这块内存原来装的什么值就值呗,上一个程序留下来的,我就直接拿来用呗。

反正我新的程序要对它赋值,我干嘛,我我我我没有必要说,我再去自己去给他初始化一遍啊,没有这个必要啊,这块讲能听懂吗,尤其是写过C语言的人,写过C加加语言的人,当我们申请完一块内存,这里面有个值。

它的值是什么,这块能确定吗,如果是C和C加加的话,这个值叫做上一个语言留在这里的上一条语句,上一个程序留在这里的是几,就是几,说不定正好上一个程序留在这里的是一个password,是我的一条密码。

Very good,太好了,我就把你密码给你破了,有安全问题,OK所以在java里面就干了这么一件事,申请完这块内存之后,马上就对它进行一个默认值的初始化,这个默认值是几呢,零,好这块还能跟上的。

给老师扣一,现在大厂面积的时候,都是从一个简单的问题开始,一直顺着往里面面面看,看你能聊多深,聊多宽,刚原来开始还是聊多深的问题,现在开始都是聊多宽的问题,越来越难了,所以我每次都得给你展开来聊好。

大家看这里再来继续看,当我们执行到这句话的时候,new new对象的时候好,申请完内存里边有一个默认值是零,调用构造方法好,就用到这句话了,这个时候才会把它的值给改成八,他这个八是它的初始的值是吧。

给它附了一个初始值,所以中间有一个从0~8的过程,好零这个状态M等于零的这个状态,这个状态叫半初始化,刚初始化了一半,那最后一句呢叫a store,HISTORE的意思是建立关联,什么叫建立关联。

这个小T指向了我们初始化好的这个对象,我们再来看一遍,当我们new就这么简单,一句话,new一个对象是怎么执行的呢,执行到new的时候,申请内存设默认值好,new执行完了。

接下来执行invoke special,改为初始值八,执行a store建立关联,三三步由三部构成,抽烟喝酒烫头,周老师三大爱好,抽烟喝酒剃头,主要烫头,他就他那头皮就给烫了,好三步构成申请空间。

设默认值建立关联哎,要申请空间啊,这个勾呃调构造方法建立关联好吧,好了我们继续听我说,当我们理解了这句话之后呢。

我们再来看这个小程序,不知道你现在是不是能发现,这个小程序的毛病之所在,来看这小程序,不知道大家能不能发现,这个小程序的毛病之所在,就像关于毛病的隐藏的比较深,我就不卖关子了,直接讲给大家听。

这个呢我们仔细想一下啊,当我们执行到这句话的时候,New t 03this escape,好好听,我说,当我们执行到这里的时候呢,其实我们是有一个隐藏的this变量,当前对象嘛。

然后这个this变量指向谁啊,指向的是调构造方法的时候,这是我们调这个构造方法的时候,一个局部变量类,如果这块你实在理解不了的话,这会应该能理解啊,如果你实在理解不了的话,我稍微给你演示一下啊。

看大家能不能看得到,我们依然看他的那个呃,汇编码,V show bite code,Buy buy buy bubbite code with the class library,找到这个构造方法啊。

Initialize,这是我们的构造方法,看他的code,我们不要看它的code啊,看他的这个呃,Local variable table,局部变量表,大家看这个局部变量表里面是不是有个this啊。

看到了吗,所以说这是我们构造方法里面的一个局部变量,局部变量this好,所以说我们在new这个对象的时候,我们有一个this变量,this变量指向谁呢,指向我们正在new的这个对象。

当前的这个对象this指向它好,既然是这样的话,他new的过程不是有三步构成吗,有印象吗,第一步申请空间,第二步设初始值,这个值为零嘛,是默认值,然后把它改成八,然后呢让this指向它。

所以我们这个线程打印this number的话,我们打印出来是八,但是很不幸的是,我刚才说过,说这个东西呢它是有可能会发生指令重排序的,what会发生指令重排序。

对不对,好在哪会发生呢。

系列 5:P13:13、乱序真的会扰乱“并发”吗? - 马士兵学堂 - BV1E34y1w773

同学们你们想想看,如果这两句发生了重排序,这两句,会发生什么情况,这两句发生重排序会发生什么情况呢,会发生这样的情况,就是当我们呃new出来,然后把它的值设为零,设好了之后呢,我并不是调构造方法。

而是直接先给建立了关联,那这个题指向的就是我们班主任,就像这个this指向的就是这个number是为几为零,而这时候我们启动了线程,线程一启动输出的值是几呢,是零,好能听明白这个问题的同学,老师扣一。

所以在这个小程序里面,这就是著名的this溢出的问题啊,它叫做英文的名字叫this escape,你要你要去读那个多线程专业的书的话,你读到你未必能理解的了,而这种程序还能出问题有问题。

所以一般的情况下我们怎么做呢,这个程序怎么去修改它,听我说啊,一般来说呢,你在你的构造方法里面不要去启动线程,你可以让这个线程初始化,但是不要去启动,看这里你可以这么来写,指尖的旋律,没懂旋律的旋律。

小伙伴,你是那个什么水平啊,你可以定义一个线程threat,然后在这里呢把它给初始化了,注意看,T等于new thread是吧,new完了之后呢,我们在另外一个方法里面再让它启动,带另一方法。

Public void start,叫start t吧。

嗯然后在这里呢调用start,这块大家能看懂吗,new出来之后调用start t这么来写,再说一遍,为了防止this溢出的问题,不要在构造方法里面new线程,有同学说,老师啊,我平时从来不这么干。

但是不耽误你,有的时候很可能调用第三方的类库,不小心这么干了,所以这种问题呢一定要小心,嗯而且呢这种问题可以说出现之后呢,八辈子你见不着错误结果,可是见我见到一次之后,很可能就是灾难灾难性质了,好吧嗯。

加volatile,这跟volatile没有半毛钱关系了,目前目前跟volatile没关系啊,实际可以跑出来这种外形的效果,跑不出来,不好跑,相当的难跑,所以这个东西是存在于面试之中。

而且是特别值钱的面试之中嗯,稍微的巩固一下这个问题,这这这会大家还能跟上吗,我看有同学说跟不上,是不是跟不上,我得问问你的基础在哪里啊,如果基础太弱的话,先跟我们零基础的课去呗。

我要从零开始把你培养成为上海名媛的嗯,我们在座的上海名媛,每个每个都是有一定的经济基础的,是不是嗯,好好OK我们继续,你们继续,当理解了这个问题之后呢,我们真的来看一眼这个美团的问题啊,美团嗯。

这个美团的围绕我刚才不是说了吗,美团啊围绕着这句话,就这句话啊,object o等于new object,就这句话,这哥们大概问了七个问题啊,后来又加了两个,一共是九个问题。

第一个问题要解释一下对象的创建过程,就是半初始化,我刚才给你解释过了,第二个呢就是DSL和VOLA的问题,这个是指令的重排序,我一会儿讲给你听,第三个呢叫对象在内存中的存储布局,分成四部分。

分别是Mark word,Class,Pointer,instance data以及padding,第四个呢叫对象,投者包括什么,包括两个大项,一个叫Mac word,一个叫class pointer。

我可以这么说,大厂的面试题里头关于底层,这哥们大概承担了30%以上的面试题,Mark word和他相关的太多了,务必把它搞清楚,第四个表对象是怎么定位,直接定位还是间接定位,第五个是对象怎么分配。

从站上开始到县城,本地到伊甸去到old区,到底在内存中占多少个字节,压缩不压缩都是16个,第八问,为什么HOSPORT不使用C加加对象来代表,代表java对象,HOSPORT本身是拿C加加写的。

它中间采用了OOP2元模型,而并不是采用的C加加对象,直接代表java,为什么这里面主要涉及到虚函数表的问题,第九问,class的对象是在堆还是在方法区这块,能答对的人也不多。

十个里头有九个基本上都答不对,好不废话了,我们今天呢主要聊这个问题,这个问题呢也是跟重排序有关的,这个问题是什么问题呢,仔细听看这里嗯,嗯我们来读一个小程序啊。

这个小程序看大家能不能读懂这个,这个这个这个小程序嗯,劝退哈哈没有劝退啊,嗯你的目标呢就是个30万,这样的水平就无所谓了,这题懂不懂的,基本上都能达到,你的目标,有30万以上。

大哥这些问题好好跟我学一遍,薪水就让你涨上来了啊,这真不是开玩笑的。

好看这里啊,这个这个小问题是这样子的。

呃,大家看这个小程序,看能不能读懂这个小程序呢,是单利啊,雪狼兽都没工作,从零基础开始玩啊,我们从那个零基础的3月就让他拿了,薪水不太高吧,8K左右,零基础吗,来看这里看这里看这里啊。

我们来看这个小程序啊,这小程序呢实际上是单例模式的一种写法,我一提这个估计好同学又开始头疼了,老大什么叫单例模式呀,单例模式是单例模式,是一种非常魔性的模式,就是他的要求呢非常的简单。

当你设计一个类这个类的对象,大家都知道啊,new new这个类对象可以new好多个吗,person p1等于new一个对象,person p2等于六,一个对象好,有一些是不能new好多个的。

wife w等于new wife,一个对象又new一次又一个对象,我靠你这疯了,不可能的啊,你家wife肯定不同意的好,这时候怎么办呢,wife就想办法把自己设成单例,就是您您老人家。

甭管你有多少个放心,拿到的都是同一个人,这玩意怎么完成啊,这非常简单啊,wife2话不说先new出一个来,作为wife类来说啊,wife作为外服类来说,二话不说,先new一个出来,new一个出来之后呢。

他把自己的构造方法设成私有的private好,别人new不了,他只能我自己new好,那什么时候我想用一下这wife怎么办,专门有一个方法get instance。

把我们new好的对象给他返回回去就可以了,这样的话呢,不管你调用多少次的get instance的方法,不管你得多少次,你拿到的都是同一个wife对象好,这会儿能听懂的,老师扣个一。

这就是最简单的单例模式,单例模式嗯哼,我们重点讲的不是单例模式,单例还是相当简单的,当然呃为了追求单例模式的,比较牛叉一点的写法,人们是那个在这里面呢各种细节锱铢必较好,现在问题来了,有人就说了。

我现在还没有用到这对象呢,您二话不说给我new了,出来,啥意思,这不是占内存空间吗,能不能等我用到的时候再new,哎这简单改一下,当调用get instance方法的时候,先判断,如果等空。

最开始我有这对象,但是我不给它new出来,如果等空把它new出来,如果不等空,说明已经有了,直接拿来用,当然这种写法有问题,问题出在哪,就在于并发上面。

假如要是多个线程都调用这get instance方法,你拿到的绝对不是同一个对象,你会有多个wife,虽然这是你梦寐以求的,可是实际当中是不允许出现的,所以这是不行的,那怎么办,判断一下第一个线程来了。

判断为空暂停,第二个线程来了,判断依然为空啊,没有人new吗,那我就二话不说,new一个,第一个线程继续又new一个,所以这里会有并发访问的问题,数据不一致,因此要求修改,怎么改。

锁good方法上上锁很对。

使用这种写法加synchronized,还有多少同学理解synchronize这个事,可以这么说啊,如果说Mark word担任了30%面试,synchronized估计还要再单身10%。

这俩哥们加起来有40%的面试,都是因为他俩synchronized呢,Synchronized,等会我就不给你展开了啊,Sychronized,它涉及到的知识点非常多,我讲的话没有四个小时,估计讲不透。

Synchronized,首先第一点它锁定某个对象,这里面有个管程的概念,有个monitor的概念,我就不给你展开了,锁定某个对象,持有这把锁,你才能干某些事,这里头是两个概念啊。

第一个是锁本身这个概念被监控的对象,我们一般称之为monitor,这里监控的是谁,监控的是this,准确说监控的是this,Sorry,这不是this static,监控的是class对象。

零四的class对象,准确的说是这个对象上面的Mark word,一会看时间吗,有时间我给你展开来讲讲,没时间就算了,总而言之,synchronized所代表的含义是,只有一个线程能执行整个方法。

而且作为一个原子不可不能被打断,这个很重要,这就是并发编程第三大特性,原子性加上了synchronized的代码之后,这段代码叫不可以被打断,它具备原子性,同时也具备可见性,好我们先不聊这个问题。

总而言之,言而总之,我上了synchronized,上了锁之后,下面的这一大段不可以被打断,一个线程执行完另外一个线程才可以执行,所以绝对放心,我只要有一个线程把它给弄出来了。

那么另外一个线程再来访问的时候,他一定不为空,那这就可以保证了,不过很不幸的是,那有的人又继续的吹毛求疵,说大哥,您的锁的力度太粗了嗯,多台服务器叫分布式锁,锁的力度太粗了。

呃我看有同学说那个嗯多台服务器是吧,多台服务器的那个叫分布式锁,分布式锁的话呢,很多很多的讲讲讲的讲的太多了。

我们课程里。

在这里来自于阿里的曹老师给大家讲了。

分布式锁,分布所实现C它用的特别多。

大概分锁我看讲了多少节课呃,这是分布式事务,这是分布式分门锁。

大概呃黄老师讲的应该是两节课左右啊,各种各样的实现,那是分布式锁啊。

那个是另外的概念,我们现在讲的是单机,你先把单机弄明白了,再聊分布式嗯,我们刚才说了啊,又有人挑毛病了,这毛病什么叫做力度太粗,就是您这锁啊太粗了,别人承受不了怎么办,什么意思,就是我不能被打断的。

原子性的这段代码代码太多了,比如说这有一些业务逻辑,从数据库里读一个数据显示出来,其实这部分可以不上锁的,可以不放在我们原则性里面的,所以你能不能把这个力度给我改细点。

这个事当然也很简单,我相信很多同学应该都知道,就这么玩吗,来看看我们把这个代码业务代码给它略过去,先判断in since等于空,如果它等于空,我们再上锁上锁,Synchronized major。

零五点class static的吗,嗯上完锁new对象搞定好,15秒读一下这代码,想想看,并发情况下拿到的,是不是能够保证只有一个对象可以吗,看气问了个,为啥要sleep11呢。

sleep不sleep关系并不大,我主要是让他sleep之后,我做实验的时候能让他快速的发现这个问题啊,就是为了fail fast,Fail,这个也不行啊,原因是什么呀,同学们,你们想一下嘛。

一个线程来了,判断哥们儿,你是等空吗,等空好,第一个线程暂停,第二个线程来了,哥们儿,你是不是依然为空哎,依然为空,因为第一个线程还没有new呢,所以第二个线程继续往下运行,它怎么运行呢。

锁定对象上锁new对象好,把它初始化了,解锁把锁解开,线程结束,and好,第二个线程运行完了,这时候注意我们的instance已经有一个对象了,那么我们第一个线程继续,第一个线程下面去申请锁,抢锁了。

能抢到吗,可以为什么,因为第二个县城已经从茅坑里出来了,他已经把锁给解开了,所以第一个线程上锁成功,又new了一个对象,new了俩,所以在这里呢,虽然看上去你觉得能够解决多线程的问题。

但实际上他没解决,跑圈看看吧,我在这里睡一个毫秒呢。

主要是想快速的给你暴露出这个问题来,这样很容易就能看到这个结果,它不是同一个对象,你看我们打印的还是code,这里有什么287结尾的,这464结尾的是吧,前面还有032结尾的。

所以这100个县城里头,说不定丢了多少个对象出来,好了,菜碗豆腐司机,你等会儿你先把这个问题保留着好听,我说讲到现在为止。

我觉得你应该能理解了这种写法是不行的,因此就诞生了著名的写法。

就是这种写法来同学们读这种写法,看能不能读懂这种写法是这么来玩的,首先第一步判断诶,哥们儿你是不是等空啊,如果是等空的话,上锁哎,探头探脑了,哎哥们儿,你这个门里头是不是有人没有人呢,一探头啊,没人啊。

没人呢,哎赶紧进去是吧,上锁啊,先先持有这把锁去申请这把锁,专业的名词叫竞争,这把锁竞争好了之后,我才能进去干事,是吧,噗噗噗便便,但是有没有可能在我竞争所的过程之中,被别人给抢了,有可能吧。

所以在你竞争完所拿到锁的过程之中,再去判断一次是不是依然为空,好这就是著名的双重检查锁,英文叫double check lock,先检查一遍,哥们儿是不是等空等空上锁开始初始化,在初始化之前再检查一遍。

有没有人在我上锁的过程中,把里边的值已经给我初始化了,好,如果依然没有,那么说明没事啊,这件事我可以安全的初始化了,这叫做双重检查锁,叫double take log。

Double check check,第一次check,第二次中间加了一个lock,上锁的过程好,这个著名的double chloe,如果你愿意去阅读一些开源软件的话,就像我们课程里。

我们大概讲了20多种开源软件的源码。

你会经常性的见到这种写法。

这种写法是用的非常非常多的,啥也别说,好好掌握住double check lock,Double check lock。

两个check中间加了一个lock好,这就能保证我们现成的一致性,因为有第一个线程,如果说结束了,被第二线程已经new完了,你第一个线程上完锁之后,再判断instance已经不等空了。

那我就不需要再弄第二个了。

所以拿到的肯定是同一个,好像那讲到现在为止还能跟上呢。

老师扣个一,做一点小小的答疑吧,这里用think this可以吗,来告诉我static的方法有没有,This king,你作为一个king,一定能回答出来这个问题,当我们还没有new对象的时候。

就可以访问static,不需要对象就可以访问static,它有this吗,没有啊,没有,好菜碗豆腐司机蔡文dog,来看看是什么问题,这么一大坨,这活干的有点多呀,老师我这里有一个问题,目前这样写。

注意是目前屏幕上这样写,static第一个线程调用get什么什么,你说的是枷锁的方法和不加锁的方法,是不是能同时执行,答案是yes,反射可以破坏DCR单位,反射有可能吧,底层判断有用吗。

老师你,你问的问题简直深入骨髓,好我们先先问你一个问题啊,很多同学读到这个程序的时候都会问大哥,您这判断有用吗,完全可以不用啊,把它去掉不就完了吗,直接上锁搞定啊,喂同学们告诉我一下。

为什么第一层判断还要留着,哎说的非常非常非常的对,这个是效率问题,这是交流问题啊,什么意思,同学们,你们想一下,我现在有1万个线程来new这个对象,如果我没有外面这层检查。

我这1万个线程每一个人都要抢一遍锁,都需要锁竞争过程,这是一个很耗资源的操作,它的效率比较低,但是假如我有外面一层检查,就会发生什么情形呢,只要有一个线程new完这个对象之后。

其他线程只用执行到这一句话,不用强锁就可以不用再继续执行了,Very good。

提高效率,好了讲到现在为止还没讲完,这个程序有没有什么毛病。

如果我们这么写,有没有什么毛病。

结合我们刚才讲的this溢出问题,有没有什么毛病,你们想想,有吗,可能返回NO,你怎么会怎么可能会返回,now大哥,好我们这小程序截下来,对照我们刚才的,半初始化对象这块,回顾一下啊。

new对象呢a new1半调构造方法初始化,然后建立关联是吧,好我们来看这句话,来来来来对比一下小程序,我贴到这啊,看这里对比这个小程序,我们现在假设第一个线程来了,大哥第一个线程,第一个线程来了。

第一个线程刚刚new到了第一,就是刚刚我第一句话new也就是初始化了一半,这时候M值是几是零,正好在这个时候发生了指令重排序,刚才我们说过这个指令重排序呢,这这哥俩换了顺序了,再看一遍。

第一个线程判断为空没问题,上锁没问题,然后开始new这个对象没问题,new到一半的时候,指令发生重排序,然后这个小T就建立了关联,注意这个小T指向的是一个半初始化对象,哥们儿穿衣服穿了一半就出来了。

那么你猜猜看,如果这个时候正好来了,第二个线程会发生什么情形啊,还没有来得及调构造方法的时候,第二个线程来了,第二个线程来了之后,首先会判断哥们儿,你是不是等空,对不对啊,等空吗,不等空。

你已经指向对象了,怎么可能等空,那既然不等空的话,来直接拿过来使用好,尽管你穿了一半衣服,我就直接拿来凑合用吧,能看懂的意思吗,所以这种写法是有问题的,这种问题呢比较的晦涩难懂,看米兰的老铁匠。

你又开始跟着卖弄了,我已经向劝过你了,当你水平还不够的时候,尽量少说话,volatile保证不了原子性,volatile只能保证可见性,只能禁止重排序,感觉他是故意的嗯,有道理,好这块能跟上的。

给老师扣个一,再通过这几个小问题的讲解,我觉得你现在应该梦小二跟不上是吧,可不想回头听我们珊珊老师课啊,我们是零基础的课啊,有有一个有一些小伙伴自己带的,就是那个那个我们零基础是小班课,特别小,十个人。

一个班不超过十个人,有班主任老师带着你,然后由我们的授课老师在里面,有什么问题随便提,哎就这么一个小班慢慢辅导你走向成成年好吧,小班多少费用,七八千块钱吧,好像是就是带你到就业这种程度。

好听我说嗯嗯只到现在为止呢,我觉得你应该会产生一个很大的印象了,就是嗯乱序这件事儿,在单线程情况下是没有问题的,为什么,因为它本身就是说单线程,不影响单线程的最终一致性嘛,所以单线程一定不会有问题。

但是在多线程的情况下,可能会有各种各样特别麻烦的问题,所以我们必须得有一种机制,能够在特定情况下禁止他重排序,这是架构师的课程吗,对这是架构师课程里头的三大部分那种,其中一个基础算法架构。

三大部分中的基础部分,架构师,我们肯定得奔至少30万到70万年薪吧,好在这种程度下,底层是必问的,必问底层,很多人死就死在底层上好了,大家听我说,再重复一遍,我讲到现在为止很,12我们得有这种机制啊。

得禁止他,不能让他重排序,来告诉我怎么让它不让它重排序,不让他重排序这件事怎么完成。

当然刚才说了啊,这种情况下会产生不必要的后果,好下面有一大堆的问题。

一大堆的问题,第一个呢我先呃呃呃先解释这个吧。

就是哪些指令可以换顺序。

其实刚才我说过这个问题了,如果是在底层的话,任何指令只要是能满不满,不影响单线程最终一致性,他就可以换,但是在JVM层面,这个规则叫happens before原则,估计有很多同学应该是看过这个单词的。

叫happens before,这话意思是说呃,某某东西一定要发生在某某东西之前,这是JVM的规定,并不是指令的具体实现,借着这一点好。

如果你想详细了解这句话的话,去读老师看过的书,这本书叫java language specification。

这本书只有像老师这样无聊的人才会去看。

一般人不会去看这本书,第17章的第4。5节。

Happens before order,There are two actions,Can be ordered by a happy relationship。

我就不给你从头到尾念了,一共有八条规则。

只有开发java虚拟机的人,只有开发java语言编译器的人才会关心。

一共有八条不讲了,请你不要去背它,没有任何意义,没有人问问也没意思,都是很很简单的这种这种呃很自然而然的问题,比如说县城只有先启动了之后,才能执行其他方法,这不废话吗。

好。

我讲到这里。

系列 5:P14:14、怎么阻止指令之间的重排序? - 马士兵学堂 - BV1E34y1w773

好下面我们讲的在什么情况下,我们怎么阻止线程之间的这种怎么阻止啊,这种指令之间的重排序拿什么阻止呢,听我说阻止重排序这件事分成两个层面的问题,网上很多文章不分层的讲,你根本就看不懂。

网上很多文章包括讲缓存,讲MESI,讲缓存一致性协议,讲volatile,你看不懂的原因就是因为他们没分层,我们分两个层面讲,第一个层面呢叫做我们忽略java虚拟机。

我们先不考虑java这种语言跟语言没关系的,CPU汇编指令级别禁止两条指令重排序,这件事怎么完成,听我说这件事是这么来完成的,就好比两个人排队,一二排着队去辨别,总是要有一个上锁。

便便完之后解锁另外一个人才能出来,好这哥俩要想换顺序,我不想让他换怎么办,我中间给他隔个板不就行了吗,给他放个屏障不就行了吗,不让你越过去。

啊老师这个文件可以分享给我们吗,不可以太多了。

我们内容非常非常的多,大概160多页吧。

跟老师学VIP不就行了吗,而且你只有只有只有这个文件,也也也也也没有什么的,好吧好,这是第二版啊,就是你现在可能往后看的是第一版,现在我们就是第二版了,每年也在升级的好看,这里我们来说这个有序性问题。

所以第一个叫做内存屏障,再说一遍啊,我现在讲的是一个底层的概念,底层概念指的是CPU级别,汇编级别,两条指令之间,我不想让他换顺序怎么办,中间给它加一条屏障,屏障是什么,是一种特殊指令。

当CPU看到这种指令的时候,他前面的必须先执行完了,再去执行后面的这块能理解吗,这哥俩就换不了顺序了吧,我先上一个执行完,你他已经死了,你不可能死在前面了啊,你不能说那个你死在一个已经死了的人的前面。

好这块能get到的老师扣个一,当然这种指令你就别背了,对这种指令你就别背了啊,像英特尔的话,它就是三三个,第一个叫LFS,FS和FS,它是CPU特的指令,其他的CPU用的可能不是这种指令。

所以你未必能够说呃通用,但是啊这是这是这是底层级别,还有一个层层面是谁呢,是JVM级别,JVM级别是怎么禁止两条重排序的呢,我这VM两个,你看看刚才两个线程对吧,这两个线程如果说不禁止。

我们那两个重排序的话,他有可能也会产生各种各样的毛病,好它是怎么定的重排序的呢,JVMD的重排序是用volt的关键词实现的,有同学说了,what这这这这这听上去很不可思议啊,怎么怎么做的呢,看这里。

这也是那个,美团问的问题,他说你的这个定义的这个对象,前面要不要加volatile,答案是要讲ja volatile,跟不加volatile有什么区别吗,区别就在于。

加了volatile修饰的这个变量不可以重排序,有同学说了,老师你这个问题有bug呀,你这个重排序指的是指令之间的重排序啊,你怎么修饰这个变量,它居然还能重排序,这是啥意思呢,嗯好大家听我说。

这句话的意思呢比较复杂一点,嗯一般面试也没人问啊,你大概理解有这么一件事就行。

这件事情呢是这样子的,好看这里,作为java虚拟机的要求,java虚拟机的规范要求,这个是另外一本书,如果你感兴趣,你去读,不感兴趣,交给老师,老师帮你弄好了,你那个直接站在老师的肩膀上继续前进就可以。

你能省好多的精力和资源啊,java虚拟机的规范。

这个规范啊非常的复杂,只有做虚拟机的人才会去看嗯。

老师没事做过几个虚拟机,所以我要读一读好虚拟机的规范的要求,凡是用volatile修饰的东西,必须去,不能说是凡是用volatile的东西,就是说凡是你只要去实现一个java的机,你必须在原语级别。

在汇编级别给我实现这四种屏障,这四种屏障类似于CPU的那种汇编级别的屏障,特殊的指令,这几种屏障分别叫load,Load store store,load store和store,Load,同学说。

老师这这这这这不是成绕口令了吗,太难理解了,其实非常容易理解,我花30秒给你讲清楚,load叫读,store叫写,如果是load store这样的屏障,这样的屏障,Load store,他的意思是。

前面的这条load指令,不可以和后面的这条store指令换顺序,这哥俩不能换,哦我讲完了应该没超过30秒,剩下三个还用我讲吗,我知道right是写对你知道women是女的。

你就不知道girl也是女的是吧,咋那么轴呢,小学五年级毕业能学懂这个课吗,没问题,只要你肯学,都谁不是从5年级过来的呀,好当然这四个要求呀,再说一遍,是JVM级别的要求,不做虚拟机的人呢。

也不用不用去理他们,到目前为止,好像只有去年有小伙伴进阿里的时候,问过这个问题,其他的好像没问过,大家看看,这是他原来面面阿里面了七次给大家总结的。

七面积的阿里呃。

百度的,美团的volatile好。

这是美团的美团的问题,三轮技术面说一下,volatile完了可怎么实现的,load store组合,四个屏障禁止除外,就问过这个哎。

美团怎么那么变态呢,最近刚刚有两个小伙伴入职美团,再变态也没用,在老师这儿照样吊起来揍,好好听,我说这是JVM级别要求你实现的四条屏障,那么说回volatile这个东西,为什么能实现内存屏障的作用。

因为看这里,因为在JVM的内部,要求volatile修饰的任何一块内存,一个变量对它进行写入的时候,也就是对它进行store的时候,前面要加一个store,store的barrier。

后面要加一个store load barrier,好,这句话是什么意思啊,这句话的意思是说,当我们对这个变量开始写的时候,写入前面的所有的写入必须都给我全写完了,我才能继续写,后面所有的读操作。

必须等我写完完成之后,你才能开始读,好这条叫读操作,对这块内存的读取怎么读啊,等我读完之后别人才能读,等我读完之后,别人才能写,好了,这就是volatile是怎么实现内存屏障作用的,那么分析刚才这个。

我们volatile修饰的那个对象的话,他前面有这个barrier,后面有这个barrier,你还能够说那两条指令还能换顺序吗,想想那两条指令,一个是去读它,一个是去写它对吧,构造方法不是要往里写吗。

是不是往里构造吗,我是不是得等它全都弄完了之后才能往里写啊,我是不是等我写完了,别人才能读啊,还能换顺序吗,换不了,好这就是为什么要加volatile的原因,来听明白的老师扣个一,我听懂了。

当然我讲底层的一般讲的比较底,明白了80%是吧,写了才能读,读了才能写,冲突了咋整,按顺序来啊,马老师,我想听广告了等着。

系列 5:P15:15、volatile底层实现原理 - 马士兵学堂 - BV1E34y1w773

当然我讲到现在为止呢,你应该大体明白了,这个至少是这个这个有序性这件事是怎么回事,明白了吧,应该肯定比原来应该清楚多了啊,就是并发编程的三大特性之有序,按顺序来是吧,首先第一点不一定按顺序。

不按顺序的原则是,只要不影响单线程的最终一致性,在多线程情况下不按顺序来,会出现莫名其妙的问题,著名的this1出问题怎么解决这个问题,加屏障,底层屏障是汇编语言。

JVM级别层屏障是一个逻辑上的四个屏障,volatile修饰的读和写需要有这个加加这些屏障,好那现在问题又来了,讲我们今天的最后一个问题吧,比较深入的最后一个深入的问题,好看这里。

volatile到底怎么实现的,它底层是那些个l fans,i'm fans这些来实现的吗,好如果你想了解这件事的话,比较复杂,还想听吗,别讲了,要不然下面这个有点难了,就太难了,嗯讲到这。

Ok m e s i,这跟MESI有半完全关系,MESI是解决可见性问题,这里解决的是有序性问题,大厂吊起来揍这个够嚣张对,没事啊,来这底层的,反正他敢问底层,你就吊起来揍就行了,想听再讲会是吧。

那我慢慢讲,我慢慢讲嗯,因为这块最后一块知识呢相对比较难,你仔细听看能不能听得懂,认真听,刚才我说过了啊,这是什么意思啊,大家咋说呢,还是拿程序举例子吧,我们看这个啊。

这个volatile修饰的变量manager06instance,这个变量在这个变量里面,我们去看它的二进制字节码,View show bide code with class library。

这个工具很好用,建议大家拿下拿下来用,我们看到它的fields field只有一个,就是它的这个变量嘛,本地本地变量只有一个,就是这个instance,点进去你会发现这哥们呢有一个修饰符,看到了吗。

Access flags,这是它的修饰符呃,这个修饰符呢它有三项构成,00X004A代表private static volatile,这里面如果你不理解的话,我在外面那个课里专门讲过这个问题啊。

拎过来。

但是我要讲这个有点有点有点有点多了,看一眼work closet jvm,讲这个课的话,这个class文件结构啊,因为这个里面是专门讲过,我是专门讲过这个class文件结构的,就是基于java1。

8的这种class文件结构,一个class文件每一个字节到底代表的什么意思,它的x flags,如果它是private是什么意思,如果是static是什么样的,如果加不加volatile是什么样的。

这几个值混在一起,最后得到的结果就是0X004A,所以你看到0X004A的时候,你会知道它是private static volatile,好,现在的问题是我知道了啊,这哥们是一个讹的东东。

现在的问题是JVM读到这个volatile之后,读到这种volatile之后,它到底是怎么处理的呢,同学们,你们想想看,我作为一个java文件,我写了一个volatile,我编译成class文件。

我的JVM读这个class文件读过来之后,我发现其中有一项是volatile的,那么这时候他是怎么处理的呢,下面我要讲这个问题,好看这里,这个问题是这样子来处理的,如果你想了解JVM是怎么处理的。

你是不是得去阅读JVM源码啊。

JVM源码是拿C加加写的,没关系啊,同学们想成为牛逼的架构师吗,牛逼架构师,有同学说老师有多牛逼,看着玩吧,你这个纵横捭阖,想到哪讲到哪好不好,有多牛逼呢,好我们有一位29岁的。

到目前为止没有没有人能超过他,比他更牛的,29岁的小伙,学完我们课程之后,大概的简历是这样写的,当然,他这个有点难,一般人呢达不到,不过没关系啊,我因为我们教东西呢,一向是认为你最好追求比较高的东西。

100万年薪没追求上,只追求到50万,good好,但是作为我们来讲,课程深度一定要达到这个深度,当然有同学有的有的有,有的机构呢人家最深也就30万,那你就拿你顶头就拿30万好,这小伙呢学我们整体的课好。

这是他全部的家当都扔在这儿,阿里呃,练完之后120万年薪P7加嗯,80万底薪40万股票,而且我偷偷告诉你,最近这小伙又跳槽了,中国it界给薪水给的最高的三大公司,抽烟喝酒烫头啊不对。

中国IT界给薪水给的最高的三大公司,华为拼多多字节,他跳到自己目前年薪200万以上,好这是架构师,这是牛逼的架构师好,那么成为牛逼的架构师。

有一个很重要的点叫做,不要让自己拘泥于某一种语言,语言不能成为你前进的屏障啊,你不能说内存屏障啊,我语言是成为我的屏障,这句话怎么理解,所有同学会问我,老师点NE怎么样啊,go怎么样啊,java又如何。

C加加牛不牛,swift语言值不值得学,最近rust挺热的,我要投入激情吗,PHP听说是世界上最好的语言,JS现在越来越牛,什么都能干,前端后端都能写,汇编哇,听上去就很牛,C语言写底层的。

我一定要学好,请问老师,我应该选哪种呢,来有这种问题的,给老师扣个一,有没有有没有这种问题的,应该有啊,这是入门级的问题吗,小小问题吗,是不是,好所有同学听我说,我今天讲的东西其实跟语言有关系吗。

没关系,但是当你如果让你的工作岗位,就局限在某一种语言层面,我就拿go写高并发服务器程序,我用到这样了,写业务逻辑我就拿C加加写类库,我就拿swift开发我的IOS程序好了,同学们。

从此你就拘泥于某一种语言层面,我就能开发这么一种特别窄的层面的,这样的类型的程序,其他的我干不了好,你的天花板就到头了,到目前为止,在北京地区点net天花板3万,3万到4万吧。

差不多这样go语言天花板3万到5万,差不多这样,java语言的天花板3万到4万吧,有的还包括java,对包括包括啊,你只需要用这种语言,只了解语言层面的东西,就薪水也就这样了,不管你是30岁,35岁。

38岁还是40岁,到头了,你想更进一步,请你给我建立架构,14位,什么叫做14位,我作为架构师来讲,我要购我要建一座房子,建一座building,一座摩天大楼,那这个柱子我该用水泥,我就用水泥。

这门子该用木头,用木头,同样的你构建一个软件层面的东西好,我是一个软件的高并发的,淘宝级别的这样的一种一种结构,我怎么构建接入层,我怎么处理,该用NGINX用NGINX,改用lure,用lure。

该用那个那个CDN,用CDN,该用各种手段,用什么,用各种手段好,微服务层怎么玩API网关吗,服务网格层或者是微服务层,数据的服务,从数据的缓存层,数据的持久化层,AI的处理层,AI怎么玩,排分吗。

好整体性的熔断限流,降级的处理,整体性的监控,整体性的报警,整体性的压测,整体性的链路,OK这叫做一个完整架构,这叫架构师,这块还合适用la来,我们用la这块和适用Python来good。

拿来Python来用,这块合适用java写业务逻辑,来来就是了,这块适合用构拿go一样来写好,这叫牛逼架构师,你的薪水不可限量,这块能听懂的,能接受的,给老师扣个一,人呢,可以层次不高。

但是请你打开你的眼界,好看这里我讲到现在为止,你说没事啊,他是拿C加加写的,没有关系,我们大体能看懂,我刚才说了,当java虚拟机发现一个class文件,里面有一个volatile的这种修饰符的时候。

这个怎么处理呢,这处理比较特殊,如果你想读的话,你需要读什么,你需要读那个by code interpreter这个文件,这个文件啊,这by code interpreter呃。

有点小啊,我来给你切出来,放大一下。

这个文件by code interpreter,By code,字节码,interpreter解释器,字节码解释器的C加加的文件肯定嘛,字节码解释器嘛,我读到了,我在这个字节码解释器文件里面。

当我读到了某个属性是volatile的时候,如果它是一个volatile,那么它调用了什么呢,它调用的是order access的fans方法,看到了吗,它是调了另外一个类的fans方法。

fence不就屏障的意思吗,这个由于我要建立debug环境,我得去LINUX底下,懒得去,所以我就呃definitions,找到definition吧,501,嗯看笔记吧。

我懒得我懒得给你去LINUX环境了。

就在windows底下给你大致解释,呃我们看笔记,volatile fans方法,防止指令重排序,嗯如果你想了解这个,what the fans方法到底是怎么完成的。

他最后调用的是order access fans方法好,这个分子方法在哪呢,是order access的LINUXX86in liner hp p这个文件里面。

嗯在这,Sorry,这是atomic,算了不找了。

找我得去LINUX也给你找,不找了,你就读就行了好吧,order access linux x86的实现,LINUX的实现,X86架构的实现是这么来实现的,这FS方法这个分析方法是这么写的。

他说if os is m p呃,他首先做一个判断,判断是什么,判断是is m p m p的意思,就,a market person叫多人运动,我主要我要看看你们有没有在认真认真听讲啊。

好mp的意思是什么,多个处理器好,如果你你你你你你是用的多处理器的话,多个多个CPU,那么他执行的是哪条指令,哪条指令呢,就lock指令,Lock adl,这哪是零,lock adl好,讲。

到现在为止你们应该知道了,java volatile底层实现啊,它并不是拿什么l fs m fans,什么那个等等,专门的CPU特有的屏障指令去实现的,而是采用了偷个偷了个懒,叫lock指令。

这个logo指令呢有的时候锁的是缓存,缓存锁,有的时候锁的是总线总线锁,总而言之,底层就是上了把锁,所以凡是牵扯到volatile的话,它底层就是上锁来实现的,好吧,这是讲cs大哥。

这跟cs有半毛钱关系吗,嗯这块如果再解释的话,没边了,稍微解释一下,还能跟上吗,能跟上,李老师扣一,这是LINUX吗,java是什么样的大哥,这是JVM的底层实现,java就是这样的。

嗯零基础是有点难了,那这块有点难,不过别急,因为这是年薪50万的课,你感觉难也正常,你要感觉还特别容易,那说明你就快达到这种水平了,恭喜你好,大家看这里log这东西呢叫做,锁总线什么意思。

这是一颗CPU,这是一个CPU,两颗CPU多CPU吗,去访问我们volatile修饰的变量的时候,我会把总线给锁住啊,再说一遍,比如说你可以理解为锁总线啊,但它实际上锁的是缓存,缓存锁,这个效率更高。

但是不管怎么样,你理解为索总现在更容易理解一些什么意思呢,呃我们CPU是通过一条线,去访问我们内存的数据线吗,好这条数据线叫总线,当我的一颗CPU去访问volatile,修饰的这块内存的时候。

我把总线锁住,其他CPU不许访问,听懂了吗,你什么指令都过不去,必须得等我执行完了,你其他人才能执行,来能get到这一点的同学,老师扣一,JVM就是这么粗暴,二话不说,就用一条锁总线的东西给给给锁了。

哈哈说不是有地址总线和数据总线吗,您还少说了一条,还有控制总线呢,所控制总线不就行了吗,当然严格来讲,这里锁的是北桥信号硬件咱就不提了行吗,讲讲讲讲成芯片设计了还怎么玩,好到这就差不多了。

JAVG也就问到这了,你基本上可以把它吊起来揍了,所以本质上就是一条lock指令嘛,它既保证了可见性,又保证了有序性,这就是volatile的最终实现,好当然你要观察到这个问题的话。

你要观察到这个问题的话啊,还比较复杂,应该说如果你想你想你想你想动手观察到,你得你得你得去LINUX底下去去干这件事,这个我们VIP我我我带他们观察过呃,但是五官个人就算了,太麻烦。

用HOSPORT的DISSEMBER,这个全称叫hot sport,This assember,Hot sport disassembler,观察synchronized volatile。

这时候你才能观察到要复杂,就不多说了,讲东西呢,我讲底层呢讲的应该来说是比较深入啊,呃这个呢是给大家讲的,基本上是沿着沿着沿着有序性这件事,给大家讲了半天,但其实这里头有序性呢不算是比较难的。

难的是原子性呃,其实与此同时呢,像那种底层的一些东西了,呃像这种什么都会给大家讲到啊,像什么和平写的技术啊,这都是像那个NOMA就是CDC才支持的呃,像还有像像像像像像其他的啊,鸿蒙啊,操作系统。

宏内核微内核啊,晋城县城县城嗯啊基本上全给大家讲一遍吧,各种中断嗯,好各种内内存管理同步的方法啊等等,嗯到汇编呃,我觉得呢你听完老师的底层课呢,第一你去听你们什么操作系统,你听起来会比较比较比较轻松。

看起来比较轻松,第二面试官来讲,你凡是签和java相关的这种底层问题,你就拎起来揍就行了,拿皮拿皮鞭子抽他啊,当然与此同时你会拿到比较好的薪水呃,薪水会拿到什么样的一种程度呢,我们最近的吧。

那最近的举个例子,这这这这这都是我辅导过的嗯,这也是我们整个课程的特色之一,就是我们一对一的辅导,其实是N对一的辅导,好多老师服务你一个我辅导过的啊,这个小伙是offer2选一,新水涨了30%。

最好玩的是,当他选中了一个offer之后呢,另外一个厂子开始追求他,求他说哥们儿,你来这边吧,我再给你涨点心水啊,这是女生,我们辅导之后进入的美团涨薪,涨了5K薪水,虽然涨的不是很高。

但是开启了大厂之旅,其实薪水是翻了倍了,这个显示不是不是很准确,这个薪水是翻倍的,为什么,因为他原来是12K12薪,他现在到美团之后是17K16星,你自己算一下,基本接近翻倍啊,嗯15。5新嗯。

当然现在正在念百度,还有蚂蚁哈哈,这个小管呢呃它的原来的一份薪水,8月份啊,8月1号报的名到了吗,8月1号报完名,到现在为止,最开始的时候呢进就龙湖地产,还有像什么五班啊啊都已经拿下了,他进的是五八。

入职五班一个多月了,有了美团的机会,美团又给他发发offer了,OK我当然建议他离开五八进入美团,五八算二线。

美团算一线。

有一线,当然进一线是吧,学习一周收获非常大,现在学了一周的VIP收获很大,老师讲的太好了,一下就听懂了,不存在不懂的问题,一听完课就记住了,哎这怎么还贬别的培训机构呢,算了把这把这部分回头给删掉啊。

上学看这个看不懂是吧,其他无事全全懂了,字节校招操作系统就能忘了。

通知一下这方面的课程都有来就是了,老师的课你牛逼就牛逼,在从零一直带你到年薪120万以上,好介绍一下我们的课,我们课全称叫MC,我从粗的层面介绍好吧,我介绍那么细,课程的全称叫MCA。

课程大概是这样来安排,MCA的全称叫马士兵certified architect,就是我们认证的architect,认证的架构师大概涵盖了从零到15万年薪,从15万到30万年薪,从30万到70万年薪。

从70万到120万年薪这样的几条路线,好如果从直的角度来讲,从P5到P6到P7到P8,好这一个课全包含了,呃大家听懂这意思了吗,好课程量比较大,所以需要我们一对一的做规划和指导服务。

这个服务所带来的效果就是短时间跳槽,涨薪进大厂,你来就是了,学完我们的高层知识体系,从如果从从课程角度讲呢,是大概分七个大的方向啊,如果是从课程角度讲,从年薪角度讲,分几分几块,从那个直体角度讲分几块。

如果从从从从这个课程角度讲,那东西就比较多了,底层的源码的,算法的架构的项目的设计的非常非常多了,就哈哈,我就不给你一一弄完了,我给大家举几个点就行,在老师这儿的课里,其他任何一个机构都没有的。

给你举个例子,比如老师这会带你真真正正的落地架构师,什么叫落地啊,有没有人自己亲手从一台机器都没有,一个节点都没有搭,一个类似于淘宝能支撑百万的QPS的,这样的一个架构出来,你具备这样的架构师水平吗。

没有吧,好吧,这里老师会带你做,是美团的老师啊,他在阿里也待过,美团也待过,他带领大概接近十个人的团队来再造一个淘宝,而且是真真正正的给你搭建分布式系统,全部拿出来搭出来,分布式id配置中心所集群事务。

集群服务集群,网关集群,注册中心,集群监控集群,MQ集群,ES集群,MYSQL的集群等等等等,全部都比你比从头到尾都给你打出来,让你真真正正能够落地,就是咋说呢,你的那种架构师级别的东西,嗯嗯先过。

演示一下吧,And where i is architect,原图去哪,嗯这张图拎出来很多同学呢,可能那个见过类似于这种图啊,我也知道有很多,有很多培训机构就培训这种这种东西,这东西是什么呀。

就是我们啊我们把它们把它称之为PPT架构师,哈哈两三个月的课啊,每周两次课,三次课,嗯然后呢我给你讲啊,这个地方应该有一个DNS啊,这个地方应该有一个防火墙啊,这个地方是运维参与的,这地是开发参与的。

哎这个地儿呢是一个负载均衡,这个地儿是MQ啊,这个地儿呢就是大数据了啊,这个地儿就是K8S集群,这个地儿就是CCD,这个地是docker,这个地是MYSQL集群,这个地是阿尔萨斯的集群,好。

你看完之后觉得我靠,好牛逼啊,见过吗,见过这样的同学,扣个一来,你们你们在企业里做方案是不是也这么做,哼看完之后觉得听完觉得特别爽,一落地啥都不会好,我们的看法是带你从头到尾真正搭一个。

我们在阿里云上大概60万1年,这是花出去的真金白银,就是为了讲好课这件事我们是不惜血本,60万1年,这里的每个节点全买下来,但你从头到尾搭,可以吧嗯嗯来,能感受到我们就是为了教好一门课的苦心呢。

哈给给点鼓励啊,老师扣个一,这事还没完啊,这事还不算完。

我们还干了一件事,你们可能就是还是那句话,就是你看到的这些没有人做过哈,就只有我们做呃,腾讯课堂本身他的一堂课两个小时,找东西不好找怎么办,看到了吗,我们现在一堂课给你干到三到5分钟。

35分钟一节课来就是了,复习起来特别好,复习想找老师吗,来这堂课我不会了,马上直接问老师啊。

来就是了啊,那个为了达到好的课程效果,真的是不惜血本,再给你举个最简单的例子,我刚才说完,我说我那个架构师呢可以让你落地,很多同学可能就说了,老师我要去阿里云上,要买的话,是不是也得花60万。

你可能花不了60万,但是我估计你得花1万,就是你想搭那环境下来,你个人要想临时性的,这一个月我就练习练习,花1万块钱,几十台服务器,上百个节点,那不是开玩笑的,没办法,我们大概花了接近三四十万。

搭建我们内部的私有云,专门为学员服务的,这是我们自己的私有云平台。

登进去,啊这是我们的整个的监控监控大屏了,我们云主机,我们自己的这种网约车项目啊,自己的运维产品,自己我们自己的app等等等等,全部都是搭在我们私有云平台上的,好这个平台,对外开放免费的。

能体会到良苦用心吗,这个是一个我给你请的老师,BAT勾的一线大厂的,北京的,不是长沙的,不是武汉的,不是那种三四线城市的,也不是像什么五八了,唯品会了,这种二线大厂的,全是一线大厂,带着你们学习。

想进阿里吗,你想知道阿里P5P6P7P8怎么玩的吗,找曹老师就行了,他原来叫阿里毕业吧,不能说阿里毕业的阿里,阿里出来的程老师,阿里的P8,你达到他的级别,120万年薪以上了,干就是了啊。

好我说的这个大的层面,有同学说老师您讲了半天底层,你跟我聊大的层面,那底层你有啥呀,底层就更多了,左老师的算法课有没有听说过,所以从最基础的基本数据结构开始讲,到基础的算法,到高频的力扣刷题。

刚才给你看评价了,没有比他讲课讲的更好,好,包含在我们整个课程包里,最后给你个结论吧,2000小时课程,别人家300小时,有的人号称1500个小时啊,逗着呢,翻来覆去讲了五次,号称1500小时的搞笑呢。

2000个不重复的课时,是别人家的七倍,价格1万2000多块钱贵吗,不要说贵,钱能解决的问题都是最便宜的。

看效果强力指导进入独角兽,独角兽啊,我们是真真正正真的是连续的指导,他好几个月抽空面试,涨薪3K1年就3万多咋整,三线城市的大量成员,三个月涨了20%的薪水,三线城市的大龄啊不是很高。

但是一年涨回学费来总是太轻松了吧,裸辞一个月涨薪3K回到行业,31快32了哈,刚办了离职,经过一个月的学习,两个offer涨薪4K,收了四个offer,年薪涨了7万,你说1万多块钱贵吗,记住有效果。

良品铺offer9K涨到1万5,一个月,欧弟和中移动两个offer,3月份刚找的工作,靠刷算法涨薪6K,这就是刷左老师算法了,37岁两个月左右,55万干到70万,杀进美团,待遇都是总包。

70左右,大概涨了27%,别说贵,这是最便宜的壳,2000小时,1万2000块钱,每每每小时五块到七块,好人家300小时6000块钱,一小时20,我们有20位老师,每个老师500,人家就三个老师。

每个老师2000,傻帽才觉得我们课程贵啊,好,直播接不上去怎么办,直播跟不上,看录播呀,我们最近在探索录播加直播的内容,任何一个机构都不可能保证你进去之后,就是你正好想听的直播课,这点你能理解吗。

我相信你应该能理解啊,正常人都能理解,不可能说任何一个机构都不是包括线下,你刚进去啊,就是你想听的那部分不可能没关系啊,如果有很清晰的,而且定期直播讲难点答疑来就是了啊,最重要。

我觉得学习方式呢按照我们安排的走就行,你呢最简单的,只要你肯来带着人来,老师安排你怎么学习,你就怎么学习,你达到的效果就全有了,我就想问一句,想不想要这样的效果。

其他的都是说别的都都都都都都都都都没意思,想不想跳槽,年薪涨10万的,学完了就学了三门课,就上涨了20万,你想不想收了四个offer,太烦了,不知道怎么选,想不想拥有这样的烦恼,你想就行了吗。

你跟钱有仇,跟你光明的职业前景有仇是吗,那你就别来,否则这个地儿独一无二,没有人愿意花血,本来真正投到不是投到广告上,而是投到教学效果上,6+2看了一半,这是什么意思。

因为我们有专门一对一的职业规划的指导,举个最简单的例子,大二大三,你想进到大厂7+1加一跟我们学一年,二本学校想进一线大厂,前十家,一线大厂99%让你搞定,就这么牛逼,应届生想进大厂6+1。

你跟他的路线是不一样的,飙升一到3年的相亲大厂6+2,呃我说我想那个那个那个全方位提升,MCA的再造淘宝课程,带着你所有知识点全学到老师,我想你自己算法课,老师我想加强我的竞争力,推荐系统AI老师。

我想从零基础开始玩,来老师,你说这些都是废话,我就想找短期见效一个月,我就想涨起薪水来,only one就一个月能不能行,3+1帮你搞定,除此之外,今晚有六张,VIP的黑卡,走过路过,千万别错过。

这个原来从来没有发售过的这个黑卡,以前我们是要单独卖钱,500多块钱才会有,今天晚上免费送出六张这个服务,黑卡包括什么,我们中俱乐部的终身会员,线下的活动,欢迎你参加门票免,当然要吃饭,您自己掏。

我们自己的app,就是将来你要看课程,像这一类的玩法来吧,在你的手机上,界面一样的一节一节碎片化的时间,就学习了系列化的知识,我们MCA的课以后升级怎么办,我们我们今年生了很多东西啊。

明年还会生啊,我们已经在规划之中了,我偷偷摸摸告诉你,我们2021年的课程已经在规划之中了,我们会升级设计专门的设计系列课,我们会升级考核,我会做你考题懂吗,我会测试你的水平。

您您您您您老人家到底是那个P5还是P6,还是P7还是P8好。

包含了,不用你单交钱,我们有终身的职业就业和技术的指导,遇到难题了对吧,刚才我看有同学找我聊天来着,说老师我有点害怕,说那个进去之后卡不住怎么办,有20位老师大哥。

这么多老师做你的后盾,你有什么难题cover不了的,这都是家里人有什么难题,往往老师这跑就行。

从此之后,你的职业生涯一路有人护航,学科免费重修,这辈子你随便什么时候想学。

系列 5:P16:16、互联网三高 - 马士兵学堂 - BV1E34y1w773

面试面的也多,那么我今天呢主要想给大家呢讲这些内容,面试之中可以说加分加的最高的就是互联网,三高到底是个什么东西,这里面呢高性能是怎么被体现啊,单机版的高性能。

然后java汇编我们来聊聊体能性能是怎么提升啊,然后我们来聊呢JOC诞生的来龙去脉,和它的原理,好吧,我们先聊一个事啊,就是我们说这个互联网三高这件事,互联网三高是哪三高。

不知道大家咱们小伙伴们了不了解啊,很多同学呢其实说的都不是很精确,很多人上来就聊高并发是吧哈错了啊,上来就错了,注意互联网三高指的是这三高叫高性能啊,还有一个叫high scalability。

是不是要给大家敲一下,给大家做个笔记吧,好不好,新建文档叫他嗯,断成两天训练营的一个笔记,呃做点笔记出来啊,互联网三高,这个互联网三高呢很多人并不是了解的很透彻,实际上是这三高。

我直接告诉大家答案叫高性能,高扩展,高可用,实际上这三者它们之间是互相之间是有重叠的,这里面最关键的点叫做高性能,这块是最关键最核心的,也是最值钱的,2020年后半年,咱们的小伙伴出去面试的时候。

把这块能写出来的薪资都比别的要高很多,那么这个高性能主要指的是什么,我们先说,今天我主要跟大家聊聊这个高性能啊,把这个聊完之后呢,我们来聊单机版的和那个分布式版的高性能,主要体现在哪些方面。

然后我们从单机版的一点点开始开始聊,可以吧,好高性能来说呢,其实是体现在两个方面,请大家记住我们平时所说的高并发,只是高性能中的一个层面,实际上呢它有两它,它它是它是两个层面构成,第一个呢叫呃,叫响应。

第二个呢叫吞吐,这两个呢都体都是性能的,所谓的系统的性能的两个方面叫低延时是吧,low latency啊,这个叫低延时,那么叫high throbot,这个叫什么,高吞吐量。

所谓的高吞吐量是不是就高并发,所以说我们平时所说的高并发,只是我们高性能的其中的一个一个层面呃,高性能来说呢,怎么样让一个系统达到特别高的性能,其实这是一个很很很很很很复杂的一个话题。

这东西呢你要是从头到尾的透彻掌握住的话呢,基本上到面试的时候,大厂的面试的时候呢,可以可以加的加分项的非常的高啊,好,今天呢也是我第一次,从这个层面来给大家讲高性能,看看大家是不是能够理解。

高性能实际上是包括两个方面,第一方面呢叫低延迟,也就是你响应特别快,第二个呢叫高并发,有吞吐量特别高,这是衡量你系统性能是不是够高的两个层面,另外这两个层面也是相互影响的,呃我给大家举个形象点的例子。

比如说你去银行存钱,假如说你在这里面,银行里面只有一个柜台,只有一个柜台,然后这一个柜台呢我们存钱的话需要十秒钟,同学们,你们琢磨一下,如果我想让我把存钱这个系统的性能提高,我们该怎么做呢,请大家记住。

请大家记住,如果有人要求你,提升系统的性能,提升两个方面,第一个叫降低延时,就是让你的响应速度越快越好,第二个层面呢叫提高吞吐,所以如果让你优化这个系统应该怎么做,其实非常非常的简单,对不对。

你琢磨琢磨,我要让你优化这个存钱系统,你该怎么做,比如说优化存钱系统,把原来的存钱嗯,十秒,给他优化整个我们的业务流程,对不对,我们业务流程上呢,原来存钱需要十秒,各种手续办起来太麻烦了。

我们只要把存钱的十秒能够变成存钱五秒,同学们,你们琢磨琢磨,我们系统的性能是不是提升了一倍啊,而且呢与此同时,你琢磨这件事,只要我们延时降低了,我们吞吐量是不是自然就提高了,我再说一遍,延时降低。

吞吐量自然就提高,我讲到这儿啊,你们今天来了,一定要带点收获回去,请大家把这俩词儿给我记住,一个叫响应,一个叫吞吐,任何对于说系统性能的一个优化,就从这两方面下功夫,听懂了吗。

get到的给老师扣个一延迟跟延迟有什么区别,没有什么区别啊,是吧,哎,这事很容易理解,对不对,你你你变成你本来你那个十秒钟处理一个,你变成五秒钟处理一个了,你相当于十秒钟能处理俩,你的吞吐量当然就高了。

所以呢吞吐量自然就提高,那么单纯从提提高吞吐量方面,我们说就说你原来还是十秒钟,你提高吞吐量,这时候怎么做呢,其实很简单嘛,我们就加柜台不就可以了吗,我告诉你啊,目前来说想提高的想提高吞吐量呃。

提高我们系统的并发量,说白了就是提高我们系统的并发量,这词应该大家会经常的见啊,经常见说什么高并发系统,对不对,到底该怎么样进行处理,我跟你说,提高系统的并发量,从这个简单的系统来说很简单。

多开我们就就就是多开窗口就可以了,从系统的角度来讲,就是你多开线程是不是就可以了,线程不够了,我多来机器是不是就可以了,机器不够了,我们多上上到云,我们进行弹性扩缩容,是不是就可以了,所以说到最后呢。

其实归根结底都会放到这两个层面上来,一个叫做岩石,一个叫做吞吐,所谓的优化就奔着这两方面去好,大家听我说,关于优化这块呢,有一个叫阿姆达尔定律,我不知道大家听说过没有。

嗯大多数人呢可能没没有听说过这个定律。

这个定律并不如摩尔定律呃,那么的那么的那么有名啊,但是这也是一个很著名的定律,呃,如果说大家伙有兴趣的话,那个这本书叫深入理解计算机系统,这本书当时超级厚啊,我不建议你去买下来。

仔细去读它这本书的第16页,专门讲了阿姆达尔定律,这个定律呢其实它的最核心的点就在这儿,他要你要想显著的加速整个系统,必须提升全系统的相当大的部分的速度,这什么意思呢,说白了很简单。

就是你想提升延时这块这块给大家复制下来啊,阿姆达尔定律。

就要想显著加速,整个系统必须其中全系统相当大部分的速度,就是你只提高一部分不行,你只提供了一个点,我们整个系统处理下来需要ab CD e啊,好多个点,你只提升C点D点,这事是不行的。

你得把ABCDE大多数的点全都提升好了,你整个系统的性能才能,整个系统的延时就是食盐这一块儿,这还不是说吞吐量,整个系统的这种食盐这块,他才能够得到显著提高,所以我们可以这么说,想加速整个系统。

想让系统的性能得到提升,根据阿姆达尔定律,我告诉你比较难做到,就比较难,你得把系统的整个层面提升,才能够得到我们比较高的一个性能提升,所以现在很多人他偷懒,他在这块呢并不下太多的功夫。

他把大多数的这样的性能的提升都放在哪里了,放在提高吞吐量上面了,听懂了吗,这块我不知道我是不是讲的有点有点抽象了,所以现在呢正是因为这个考虑,诞生了一系列的系统架构,嗯阿姆达尔阿姆达尔黑,写英文吧。

SADIE定律,告诉我们提升系统的响应延时,比较困难,所以现在很多系统的性能提升,体现在提高吞吐量上,那怎么提高吞吐量啊,这里就诞生了,各种各样的系统架构,当然从系统架构角度来说呢,就非常非常多了啊。

嗯我我这样啊,我刚才说了,我说那个我们要优化整个系统的话呢,实际上我们要么优优化它的响应,要么优化它的吞吐量,呃我不知道大家伙有没有优化系统的概念,不知道大家有没有优化系统的概念,如果有的话。

如果有的话,那你给老师扣个一好不好,如果没有的话呢,我给大家举几个小例子啊,这样我给大家举个小例子啊,举例比如说啊,我们说我们对系统来说,我们做了一个集群来,你告诉我一下。

这个东西是优化响应还是优化吞吐,说我们给系统做了个集群,我们单机撑不住了,我们就给他做了一个集群,让好多台机器共同提供提供服务,这很明显是油画吞吐是吧,同学们肯定的,能不能既优化响应,又优化了吞吐量。

优化了响应,听我说啊,记住只要你优化了响应,本身吞吐量就自然而然会被优化,好吧嗯,还有一个啊,比如说我们做了负载均衡来,同学们告诉我你是在优化响应呢,还是在优化吞吐呢,吞吐对没错啊。

比如说啊我再给你说一个,比如说我们做了缓存来,你告诉我你是优化响应还是优化传统,响应说的很对,比如说我们缓存本身又做了负载均衡是吧,又做了集群,那就是你既优化了响应,又优化了吞吐,听明白这意思了吧。

所以总而言之,言而总之你各种各样的手段,要么我们优化它的响应,要么我们优化它的吞吐,我再给大家举个例子,这个看大家了不了解,我做了JVM的优化,这个是优化了什么,响应对吧好,我现在做了分库分表。

我做了什么优化,吞吐对不对,嗯当然同学们,你们琢磨一下这分库分表,这表小了,它的响应是不是也就提高了,是不是,所以呢这两个都做了,OK嗯我再给你说一个啊,比如说我们说一个更详细一点的。

我们说tom cat呢,我们用了非阻塞协议,原来tom cat我们用的是阻塞协议,现在我们用了非阻塞协议来这个,这个我们是优化了什么,优化了响应,优化了它的响应之后,记住它的吞吐自然就高了啊,响应快。

吞吐自然高,这个很正常好,我们再说一个,我们用了MQ,我们用了异步,这个跟tomcat非组织协议其实本质是一样的,对不对,嗯蒙了是吧好吧,蒙蒙蒙蒙了就算了,不举例了,反正总而言之。

在你的整个系统架构里面,你去优化你的系统架构,不论你采用什么样的具体的技术手段,我相信我建议大家呢先从框架上理解,就是你要么优化它的响应,要么优化它的吞吐量,就看你们追求什么这块大家听懂了吗。

MQ叫做message,Q叫消息队列啊,这些技术都听过,但是没做过,老师这课都有啊,这里所说的所有的全有,放心吧,嗯那个啊,我讲课呢愿意从更高层次上来,带大家认识一些东西,一些东西啊,吞吐响应是个啥黑。

还有人有这个问题吗,我看到有小伙伴,那个他的他的他的他的这个问的比较简单,这样啊比较简单的问题,我就回答你一次,我会快速的回答你一遍,响应是个啥,就是你比如说你去银行办存款,他用了十秒钟。

它的响应时间就叫十秒钟,就这意思听懂了吗,用了十秒钟帮你做好了,这就这个就叫响应你,你你去访问一个页面,这个页面一秒钟你就你就访问到了好,这个响应就是一秒钟,当然这里面还有细的概念叫TPSQPS。

这个我们回头再说,不着急,大的层面上处理完你这个请求的时间,就叫响应每秒钟,或者说每每个时间单位能处理多少请求,这个就叫吞吐,好了,大家了解高性能这件事情呢,它的本质,最后其实有的时候呢。

我喜欢从大的框架给大家讲东西,呃,稍微的说的虚一点,就是我希望大家伙一定要建立一个,框架这样一个概念框架,我说的这个框架呀,并不是说呃,说说说什么java经常用的这些个组件框架啊。

spring spring的,不是那些,我说这个框架是说从大的层面,认识技术和其他事物,呃我稍微从大的层面给大家讲一点点,同学们有没有听说过这样一句话,年轻人就要去多犯错,年轻人要去多犯错。

为什么要做犯错,因为吃一亏长一智,他慢慢就成长了,应该听说过吧,说年轻人不怕失败,是不是没错,同学们听我说,所谓的犯错有两类错误,一种呢叫做细节性错误,就是你大的方向是对的。

但是呢你可能犯了一些很小的细节性的错误,你方向是没问题的啊,我是走在正确的方向上,我是要往嗯,整个社会呢他就正在拥抱新机的时候啊,5G物联网,我奔着方向去,中间你可能走歪了一点点,走歪了一点点。

但是你大的方向是没有的,这种错误没关系,随便犯,多犯一些,让你成长更快一些,但是还有一类错误叫框架性错误,人生这辈子框架性错误大概就那么两三回,这玩意儿你要是犯了,可以这么说,你再做努力全白费。

我给你举个最简单的例子,高考别人都在那学习,你玩儿了,你得用多长时间才能够把这个错误给揪回来,你有你能理解吗,这个就叫框架性错误,比如说别人在那里玩后端玩go on玩java,然后你在那里玩什么呢。

你在那里玩的是嗯,从来没听说过啊,这个这个这个这个pascal,你在玩这个,你在玩SPSS,这个就叫框架性错误,这大家能理解吗,很多人学东西呢,他是从细节开始学懂吗。

就是咱们从小到大的教育都是从细节开始学,以至于咱们认为我细节学好了,我这个我这个人呢就一定是生活的很好啊,就这个这个这个,但其实啊在我看来,所有人是犯了很多很多的框架性错误,还在那个细节里头使劲钻。

你越钻错误就越多,越钻越钻,你错的就越远,嗯希望大家伙能抬头看路,路在哪里,路在何方,看那个整个的发展趋势好吧,看准这个之后,认准方向,先把框架搭好了,搭起来,搭起来之后,你在里边再生那些树枝,树叶啊。

树的那些个脉络,那个就方便的多啊,也好得多,也不容易犯更大的错误,所以大家伙可以犯细节性错误,但是不要犯框架性错误,那么举个最简单的例子,你你为什么现在很多人是婚姻,或者说男女朋友之间啊。

结了婚之后就特别别扭,特别多,为什么呀,是因为你们从来没有认认真真的选过,你的结婚对象,说这个人不错啊,我们认识三天啊,哎呀太爽了,然后呢,你后面就用各种细节性错误,去纠正你原来的大方向错误。

这个人适不适合你,这人本来就他不适合你,结果呢你就就是就是就是凑凑合合的是吧,然后呢就结了婚了或者处了对象了,实际上你从来没有想过这个人到底适不适合,是因为你在选对象这方面,你没下功夫。

犯了这种框架性错误,你想用细节性的各种东西来弥补,怎么去维护关系是吧,各种各样的小细节有用吗,屁用都没有,中国呢拿国家发展来说,中国改革开放发展也犯了很多细节性错误,但是大的框架性错误犯过吗。

基本没有啊,我们有好多那种,那么他做了很多具体的东西吗,没必要,框架搭好了之后,我们很多东西都可以做的比较到位,慢慢慢细化就可以了啊,嗯总而言之,言而总之希望大家伙学东西也好,或者是后面走后面的路也好。

先建立框架性的东西,如果这事还不能理解呢,我最后再给你举个例子,通俗的说一下,呃,相信每个人的手里一定是有好多好多的,各种各种的视频,各种的文章啊,各种的收藏夹里面装了好多好多技术性的东西。

这个就相当于什么呢,捡了很多零件,比如说你拿一个啊,你你你你你你弄了一厂子,这厂子里面有好多零件啊,这个小螺母小螺钉啊,方向盘小轮子特别特别多,这些零件你学好了之后,每天都来学习学习,拿出来看看啊。

这还算很不错,每天感觉自己都在进步,但是当你把这个零件想给他攒起来一辆车,你能想象这个难度吗,有没有有多少人是学了很多很多细碎的东西,让他做一个实际项目,发现无从下手的,有没有有的话给老师扣个一。

应该有的是我觉着零件都很好,学零件就像认字认词,顶多组个句子,你要写一篇优质的文章,作文这事儿难了去了,其实啊这事应该反过来知道吗,应该先学整车,先学框架,也就是说我一般都会建一个学习方法。

叫做囫囵吞枣,很多人都不建议,但是我一般会建议大家叫囫囵吞枣,从整车往零件选,就是呢你上来二话不说,能够理解我们所做的这个东西,能够做一个什么样的项目,懂吗,哎这个项目里面有好多细节,你可能没有掌握的。

通过这些细节觉得我哪哪有所欠缺的,再去学这些零件,当你囫囵吞枣能做完一辆车的时候,你就可以用碎片化学习去学习零件了,因为你发现有好的轮子,把原来轮子剃掉就可以了,不知道我说的重要啊。

咱们学习方法就聊到这儿好吧,我希望大家伙在你脑子里建立起来,这么一个框架的概念,你把这个概念建立起来,今天就没白来,不要老盯着细节,首先定大的方向,大的方向对了,再去努力,大的方向不对。

再怎么努力也白搭,好了不废话了,这个讲的有点有点远了啊,OK反正总而言之,如果大家伙以后聊性能这件事,记着两个层面,一个叫响应,一个叫吞吐,响应提高了吞吐自然提高,但是响应不太容易提高。

所以很多人在吞吐上做文章很简单,现在的云原生,K8S是不是直接在吞吐上去做文章了,没关系啊,你说你想要慢没有关系,我们就动态的,扩缩容动态扩缩容没有关系,你你需要的时候,我直接给你一堆的容器。

直接弹性给你补上来,双11双11过了再给你缩回来,OK这东西呢我预测会慢慢的干掉,Spring cloud,今天留在这啊,但是呢呃五到10年spring cloud死不了,所以你现在该学还得学。

这没什么可说的,总而言之,学到最后你会发现思想是相通的,慢慢学思想就可以了,好了不废话了,因为很多人基础不到位,我这个说的太多了,理解不理解的也不好说,OK嗯聊点具体的技术的内容,嗯大家听我说啊。

就是说刚才还有同学问说那个聊不了锁,就是我们要聊点县城这件事了,聊点具体的嗯,嗯什么情况。

嗯这是汇编。

汇编就先不讲了。

呃我们说讲了这么几个了,就简历里面的互联网三高到底是什么,你现在应该理解了是吧,大家把它背过叫高性能,高扩展高可用嗯,那么高性能是怎么体现的,两个层面,一个是低延时,也就是响应要快。

第二个呢叫吞吐量要高。

系列 5:P17:17、多线程与同步锁 - 马士兵学堂 - BV1E34y1w773

单机版的高性能,我们开始聊单机版高性能是怎么做到的呢,但这个事大家应该知道啊,单机版来说,如果你只有一个线程,它一定是做不了的,那么一定是有好多好多线程共同对外提供服务,这个时候呢。

就你就从你从一个线程扩到多个线程的时候,你就琢磨这件事,我们是不是从并发这块,就是从吞吐这块就给他做了性能的提升了是吧,原来你只有一个服务员,我现在呢给你可以给你起一堆的服务员,当然有了多线程之后呢。

就会产生各种各样的问题啊,我能从一些细节开始讲讲吧,好不好。

不能只聊粗的层面,我们要聊点细的层面好。

大家看这里啊,嗯如果我要是从这儿开始讲,那个说现成的最基本的概念,这个就没意思了,不讲了,线程最基本概念不想讲了,这个大家能理解吗,讲讲讲一点比较简单的好吗,讲点比较简单的啊,听我说嗯。

首先说呢我们说第一点啊,每一个线程是运行在不同CPU里的,就是一个一个CPU呢,通常情况下只能运行一个线程啊,不考虑那些什么线程撕裂是吧,不考虑那些什么八核16线程,四核八线程,不考虑这样的一个结构。

通常来说我们说一个线程运行在一个CPU里面,我们有多个CPU就可以同时运行好多个线程,这个东西呢就相当于增加了我们的吞吐嘛,吞吐嗯,所以我们整个性能一定是有提升的,呃那好呃,从线程角度讲呢。

我先问大家第一个特别简单的问题啊,这个呢是不是在我讲多线程的时候呢,会被很多的,会被很多的人问的一个特别简单的问题叫做,是不是线程数量越多越好,答案肯定是否定的,绝对不是啊,为什么呢。

关键是为什么同学们有这么一件事情啊,就是说我是不是无限制的,假如说我有八颗CPU,八个,我是不是无限制的,就可以往里头装各种线程呢,如果我说我装一个县城,然后啊装八个线程啊,我们的效率很高。

我要装8万个线程,它的效率是不是一定会比原来的高1万倍呢,肯定不是,原因是什么呀,原因是因为每一个线程跑在CPU的时候,会有一个叫做系统切换这个概念能理解吗,会有一个叫做系统的切换,这,个我看看。

这个我看看嗯嗯嗯。

这个东西呢会有一个现成的切换啊,叫做系统切换,那么这个切换是什么概念呢,这个切换是如果我只有一颗CPU,正在跑第一个线程下面,我要马上切换成第二个线程,它中间是要做一系列操作的,是要消耗资源的。

是要把寄存器的这些东西呢全都保存好的,然后呢再切换成另外一个线程的,就总而言之呢,我一个服务员现在正在服务一个客人,我中间是要切换切换成其他客人的时候,我是需要消耗资源的,因此呢。

因此呢我正在运行T1的时候是吧,我要切换成T2,我怎么做呀,我需要把那个T1所有的这些东西全都拿走,放一边去,然后呢再把T2所牵扯到的所有的数据什么的,唉放进来,所以这里呢会有一个线程切换的概念。

这个线程切换呢它会消耗系统的资源,所以说不是说线程越多越好,因为如果你只有CPU的数量固定啊,十颗CPU你要起1万个线程,相当于每颗CPU会在1000个线程左右里头,来回切换。

它会把大量的时间花在切换上,因此它不是说你的CPU的数量越多越好,这点大家理解是能理解的,给老师扣个一,所以说工作线程数肯定不是设置的越多越好,这是肯定的,因此呢一般来说我们让切换啊。

让切换跟我们设设置的正确的一个数量,达到一个平衡点是最好,比如说我们有八核的CPU,我们放16个线程合适,还是24个线程合适呢,如果不考虑其他的因素的情况下,还是32个线程合适呢。

这个东西呢它一定不是线性增长,它一定有一个平衡点,到了这个点之后再多,它性能可能下降了,能听懂吗,所以说要找到这个点,这个呢也是被经常我突然发现我讲的复杂了,呃,那个这个呢也是经常会在大厂里。

会不会有人问的说,你设置你总的线程数的时候要设多少合适,要设多少合适,24没啥依据,对现在人家问你的就是这个依据,有没有人被问到这个被问到过这个问题嗯,应该有对,实际上这时候呢有一个公式。

我不知道大家了不了解,有一个公式,这个公式是这样的,你可以截个图回去自己琢磨好吗,这个公式呢我我可以这么跟你说,你在面试的时候可以说没问题,但是真正实际工作的时候,记着我的结论一定是以压测为主。

你要模拟你真实的环境,压测的时候,如果是十个线程合适,我们就设十个压缩,20个合适,我们就就就设20个,根据这个公式可以算出来一个初始值,然后来回调整,根据这个公式算出来,如果是八个,我们就先设八个。

八个不合适不合适,调成十个试试,十个不合适调成12个试试,最后在这些里面找一个合适的指出来嗯,大家可以截个图,这是这个这个问题的标准答案,好吧,怎么确定多少合适。

实际上这里面是要你是CPU密集还是IO密集啊,今天呢我重点就不聊这个了啊,这个这聊的话就有点多了,好我们从简单的问题开始聊,那么大家伙思考一下,当多个线程共同开始工作的时候,一定会产生各种各样的问题。

比如说最常见的就是锁的问题,关于锁,关于同步,大家伙至少就算你没有用过,我觉得你多多少少都应该听说过来,有多少人用过这个关键字的,有多少人用过这个关键字,看这里,这个关键字有多少人用过的。

synchronized在你平时开发之中有没有用过吗,哎肯定是用过是吧,那么这个关键字到底是什么意思呢,我给你举个例子,最简单的例子,比如说我们synchronized某一个关键字。

然后在这里头写一段话的,有谁大概能理能能能能聊一下,这个到底是什么意思,来讲讲,保证线程安全,你说的很对啊,同学们听我说,多线程的编程呢,实际上它非常非常的复杂,要比那个嗯单线程的编程要复杂得多得多。

多线程呢它有三大特性,我希望大家伙先记住它,因为今天我可能来不及把三大特性讲给大家听,第一个呢叫可见性,第二个叫有序性,第三个叫原子性,同学们认真听我说,这里面最复杂的实际上是原子性。

可见性和有序性相对简单一些,但是也远比你想的复杂得多,我今天呢给大家讲原则性的一部分呃,可见性有序性呢我讲以前也讲过好多次了,它也是很复杂很复杂的好吧,也是面试的非常重的重灾区。

我们就拿这个来拿这个小程序来举例子吧,好不好,所谓的synchronized o,然后里面敲一个I加加,我们先说最基本的定义,这相当于什么呢,把这东西当成一把锁,说我要干里边这件事的时候,哪件哪件事呢。

中括号里包含的这件事,这件事你在中括号里面包含的这件事,我要在里面干这件事的时候,必须持有这把锁,必须持有锁,持有所才能干这事,不持有所不允许干,上个厕所,你才能在里边噗噗噗,不然的话这事你是不能干的。

因为有任何人可以冲进来,跟你屁股对屁股一块噗噗噗,你能你能受得了吗,盯得住吗,肯定不行,好这里的这个小的对象,synchronized的括号里的小对象,这个东西呢就是一个锁的最基本的概念。

他就把这个对象当成一把锁来用,当然这个里面的细节也特别多,说这个对象怎么能当成一把锁来用,是怎么做到的,平时我们说我把这门锁上,大家会很容易理解,只有我把门锁了,我这一个县城在里面干活,别的县城进不来。

对不对,但是你怎么把线程当成当把对象当成一个锁呢,同步监视器啊,没错,你说的很对,这块需要了解,需要我讲讲细节吗,需要的给老师扣个一,不需要就算了,因为很多人大家伙这种代码呢可能就上手,二话不说就写。

但这个代码的背后到底是什么意思,很多人可能真的不知道,我试试看啊,我就讲讲的简单一点点啊,同学们听我说,嗯我先把这小程序删了,小程序是我随便敲一个,嗯没呃,首先大家伙需要了解这个所谓的给对象上锁。

到底是什么概念,为了对比起见,我们先弄一个小的简单的对象出来,object o等于new一个object这块我以前讲过好多遍,以前有同学可能听过我讲的速度稍微快一点,就是我们弄一个小小的普通对象的时候。

这个对象他到底长啥样,很多人可能没没不知道,没有用过,我教大家一个东西,这个东西呢叫JOL这个类库啊,JOL它用起来非常的简单,你稍微百度一下,一定会一定会有。

它的全称叫java object layout,java对象布局,这什么意思,你看我直接用就行了,Class lay out their past instance of their two principle。

Rs,同学们听我说这句话的意思呢,就是我用了GL类库里面的一个类,我把这个对象给做了个分析,做了什么分析呢,你们琢磨这件事,我new出来的任何一个对象放到内存里面,它一定是由零一构成的,对不对。

一定是这样的,好,这句话的意思是说,把这个new出来的对象里面,这个零一到底是怎么布局的,给你打印出来啊,我们先跑跑看啊,你有一个直观的认识,你就理解了,好你看这里就是我们new出来一个对象之后呢。

我们分析这个对象的时候,这里就是在内存里面的对象布局,你如果把脑袋伸到内存里面,真的一个10101去看的话,你会发现这个对象长这样,这是一个对象的样子,好这个东西你一定看不懂。

但是美团百度阿里围绕这个东西一堆的问题,我今天先给大家讲比较简单的,同学们听我说这个东西呢,其中有一部分叫做object header,我相信你你就算什么都不懂,单词应该能读懂吧,这东西叫什么叫对象头。

比如我们真正的对象弄出来之后,是有一个脑袋的,这个脑袋呢其实记录了好多好多信息,比如说说我给你说一个最简单的,所谓的给对象上锁到底是个什么概念,Synchronized o,我们给这对象上完锁。

再把他的布局给他打出来,你看看比较一下,你就知道了,跑一下,来做个比较,自己做一个比较,这个呢是刚刚开始我们new出来的很普通的对象,这个是我们上完锁之后的对象,能看懂吗,是不是发生了变化。

我们是不是能得出一个结论来,最简单的结论,所谓的给对象上锁,其实就是在他脑袋上记录了一些信息,所谓的给你的厕所门上锁,不就是拿一钥匙咔嚓把锁给锁住吗,所谓的给对象上锁是什么意思。

就是在他脑袋上记录了一些信息,说我锁定了其他人,不许来来能get到这一点的同学,老师扣个一,所以我们说synchronize o这件事啊,所谓的锁定O指的是修改O的头记录锁信息,好这事情我就交代到这儿。

我以前讲过课呢,我把这里面的零一都给大家分析过,但是今天呢咱们小伙伴的基础我不知道怎么样,我先把这块略过好吧,嗯不管他,反正总而言之,言而总之,所谓的锁定O指的是什么呢,指的是修改O的头部记录的锁信息。

这个事儿你一定是看到了,你已经看到了,所以他一定是没错的,那么下面我们说下面这部分,这部分的本质是什么,这部分的本质是说,这部分本质是这样子的,看这里就是就是我们锁定之后的这部分。

这部分有专业名词叫critical section,叫临界区,我们先不去管它,我们聊这部分的本质是什么,本质是什么东西啊,本质是这样子的,好多个线程如果共同执行这里面的东西的时候,相当于是什么样的。

相当于是一个并发的操作,比如说这里面是什么爱加加呀,里边有一堆的操作,那就相当于这堆操作呢,有一个线程在运行,另外一个线程也在运行,另外一个线程也在运行,另外一个线程也在运行。

这个东西是好多线程在可以并发操作的,并发,如果是多线程运行这个啊是可以并发操作的,但是如果我上了锁,这就变成什么样了,我这个如果说我这个线程拿到了这把锁,那么一定是这个线程先执行。

而且呢是把这个所有代码全执行完,执行完了之后,另外一个线程拿到了这把锁,这就是那把锁,我锁定了这个类型,拿到这把锁才可以来继续执行,等我这线程执行完了,才可以被另外一个线程拿到锁之后,继续执行这段代码。

才可以被最后一个线程拿到这把锁之后,才执行这段代码,你会发现整个的执行过程加了锁之后,从并发变成了序列化执行,序列化执行,所以我们平时所加的这把锁叫做互斥锁,那我讲到这同学可能会说了。

老师有没有一种锁能够让我俩线程进去执行的,你们有没有这样的疑问,有吗,有没有有的话,给老师扣个一,这东西应该能想到啊,对不对,我现在这种锁就是特别简单的这种锁,这种锁呢就只有一种。

只有一个线程能在里边玩,对不对,然后有没有一个我能连线成一块在里边呢,当然有sure,必须有,对不对,好,那个东西叫什么,就是SAMHA,信号量啊,嗯看时间,就在这个锁里面呢,那粉丝他都死掉了。

系列 5:P18:18、synchronized本质是一把悲观锁 - 马士兵学堂 - BV1E34y1w773

信号量啊,这是那个阻塞队列哪节来着嗯,基本上是这个啊,SAMHK呃,就是说多个线程是可以的啊,是是没问题的,呃我告我可以告诉你啊,在JDK的早期呃,基本上就只有他一个,只有这一把互斥锁,别的锁都用不了。

只有这一把互斥锁,后来呢为了增强锁的一些效率,我们就提到性能了啊,为了增强性能,为了提高一些功能才诞生了这个包,这个包叫JUC,它的全称呢实际上叫做这个这个东西。

叫java utility功能。

Concurrent,并发包,在并发包里面呢有很多很多新的所所诞生。

好吧,什么诞生起来的,我今天尝试着呢给大家伙聊,聊清楚这个历史也聊清楚呢,所谓的JUC它的本质是什么,我们不是说学东西学框架吗,我们先把它的本质给他了解透了,其他的万变不离其宗。

你学习起来就方便了好多好多好,那么大家呢嗯认真听这件事啊,就是我们还回到刚才的那个那个那个嗯。

synchronized这件事,呃总而言之呢,你以后再见到synchronized的,你就不要说什么同步了,就不要说这个了,你脑子里头只要反映一件事,说我持有了这把锁之后,只有我自己能做。

我从原来的并发变成了序列化,一定记住这一点,你从并发变成序列的话,你就琢磨这事儿,它的效能效率一定是降低了,肯定是降低了,所以你要尽可量的让这部分呢执行的更快一些,就相当于你的响应时间会更提高的。

更更更更更更快一些,你的吞吐量自然就高了,这也是性能优化的一部分啊,O呃那么我们讲到这儿呢,我们就聊这个synchronized的东西,关于SYCHRONIZED,它的本质是非常非常多。

两个小时之内一定是讲不完我,我给我给他大家聊,最重要的一点,好好好好听我讲啊,SYNCHRONT这玩意儿为什么有了这玩意之后,后面又诞生了JUC,为什么,原因是什么。

原因是SYNCHRONT这玩意本质上它是一把悲观锁。

Ok。

synchronized的本质是一把悲观锁。

这是啥意思,有同学说了,怎么又出来了,悲观锁,乐观锁了啊,对没错,所有好多好多种,有全局所局部所有分段的所有悲观锁,乐观锁,有读写锁啊,有只读锁是吧,有可解锁,有多个拥有多个多。

可以可以跑好多好多现成的这种信号量啊,也有可以说好多线程一块,同时开始跑的这个栅栏等等,特别特别多,但是synchronized最早的那把锁,这个东西本质上是一把悲观锁,什么叫悲观锁。

悲观锁的概念就是同学们,你们琢磨一下,我要进去拉便便,很难便便,举例子只有一坑位,我要进去拉便便,一定有人跟我抢吗,不一定吧,啊你自己一个人在家在里面拉便便,一定一定有人跟你抢吗,没有啊,不一定啊。

是不是不一定有人跟你抢,既然不一定有人跟你抢,你一定有必要把那门锁上吗,这块能听懂吗,能听明白,给老师扣个一,就是说所谓的悲观所指的意思是说,虽然不一定有人跟我抢,但是我上来二话不说把锁锁上。

虽然不一定有人跟我抢锁,但是我也要锁定,没必要啊,你家里就你一个人,你锁什么锁,你锁锁,你自己琢磨,你锁锁这个东西不就是修改一个对象的头吗,你修改头不需要消耗你的CPU资源啊,不需要消耗你的时间呀。

他也需要,对不对,所以呢这个东西有没有人跟我抢,我也要锁定,实际上它的效率本身就不高,这块我能大家能听懂吗,能听懂给老师扣一,我再说一遍,就是不管有没有人,你都要上诉你,这个效率本身就不高吧。

那我能不能够做到说我不上锁,不上锁行不行,那有没有同学告诉我不上座行不行。

不上锁肯定不行。

万一有人锁呢,万一有人跟你抢,你正跟里边拉的欢。

突然一堆人跑进来,所有的屁股围着你的屁股,然后扑哧扑哧不合适是吧。

哎这肯定不合适,那么有没有一种我们不上锁,也能解决问题的办法呢,答案是有的,这个东西叫乐观锁,当然乐观锁的具体的实现,一般我们称之为叫CAS啊,嗯这是JUC的本质。

听我说JUC所有的锁,基本上JUC里面所有的锁替代,synchronized这种的reaction log啊,包括后面的countdown,Lch,Seliberria phase。

Rewrite log,Sumricks changer,除了LOCKPORT以外,所有的其他所本质上全是乐观锁的实现,全是CAS的实现,嗯那么为了聊了聊清楚这件事呢。

我看看啊。

我们拿这东西来举例子吧,嗯大家听我说。

这是一个最简单的案例,像很多同学呢学学学java的时候,就一定是了解过,就是我们有一直最开始是零。

然后呢我起了好多线程,每个线程里面给他加了1万次,起了100个线程,100个,每个线程给他加了1万次,正常的结果是100万。

但一定是100万吗,不上锁肯定不行,你看不上锁的话,3万多再跑一遍,不上锁3万多,为什么会这样,很简单,是因为如果你不上锁的话,有一个线程这里如果是八,你把这八拿走了,改成九。

另外一个线程也把这八读走了,改成九,另外一个线程也把这八度了改成九,然后每个线程都往回写,写了九这个九我把它覆盖了九,这个九我把它覆盖了九,加了三次,一共加了三次,最后呢这个结果只加了一。

产生这个问题的主要的问题就是由于什么呢,我有一个线程读过来之后,在正在加的过程中被另外一个线程打断了,另外一个线程已经把这个八改成九了,所以大家应该都知道怎么解决这个问题,怎么让他得到结果。

100万很简单嘛,上锁嘛,所以呢我就来了,把锁synchronized。

OK来了,把锁跑一下,看最后结果一定是100万。

100万,为什么上锁能解决啊,因为很简单呀,你们分析我们刚才的那个所说的,我们持有这把锁之后,有一个线程加完了,另外一个线程才可以加,才可以加,才可以加,才读这个新的值,才可以加,读这个新的值才可以加。

所以这玩意儿最后的结果一定就是对的,我一个线程做的时候,另外一个线程不许不许操作,但是这把锁叫悲观锁,我说过了。

我我才不管你有没有人打断,我。

系列 5:P19:19、JUC乐观锁 - 马士兵学堂 - BV1E34y1w773

那现在问题是,那么能不能够说我们不上悲观所能不能解决,因为悲观锁有没有人跟你抢,你都上锁,没完全没有这个必要,有的时候他说怎么办呢,这时候就会产生乐观锁的概念啊。

乐观锁这个概念呢,其实我跟你说啊,同学们听我讲这个乐观锁啊,好多好多概念,嗯不错,他们听我说,这乐观锁呢有好多好多的别名,就是大家伙叫着叫着呢,可能叫混了,我先说一个观点,所有的概念都是人类创造出来。

方便沟通使用的,一定记住这一点,什么意思,原始人啊,不认识这玩意儿是吧,嗯后来起了个名叫便便哦,大家伙一沟通的时候,手绳子拿手比划了一说,便便的指的是什么东西,但是这里面你创造了概念,我也创造了概念。

很多概念就容易混淆到一起,如果大家伙把精力都花费在扣概念上,你就成了孔乙己,我下面讲的这几个概念很容易混淆,但是你不用使劲抠,听我讲这个乐观锁啊,有很多人称之为乐观锁,也有很多人称之为叫自旋锁。

还有的人呢把它叫做无锁,这个名称是最讨厌的,为什么他叫吴所,我一会儿讲给你听,是因为呢他原来认为这是一把锁,所以呢这边没有上那把悲观锁,因此呢叫做无锁,叫无悲观锁,这个名字是最讨厌的,以前还有人问我。

老师无锁是不是一把锁,白马是不是一匹马,谁要跟我讨论这样无聊的问题啊,你哪凉快哪呆着去,不要跟我讨论这种问题,我们学东西叫做学以致用,你如果说为了抠概念,跟我这儿抠字眼儿,咱就别聊了,好吧好。

我还告诉你,以前有同学跟我聊,说老师这个无锁跟cs到底有什么区别,其实如果严格意义上讲,CAS是乐观锁,自旋锁,无锁的一种实现方式,但是呢基本上也就这么一种实现方式,所以说呢这几个概念从粗浅的角度讲。

全是一个概念,好讲到这儿可以继续的给老师扣一,不懂才问的,知道还问你干嘛,嗯你说的很对嘞,雨电嗯,所以我提前给你给你毙了吧,这种问题好吗,带节奏的,我一会直接踢出去啊,我直接告诉你们,谁要我带节奏。

我就直接往外一踢,二话不说好,所以我们只要聊清楚cs这个概念之后,大家伙这乐观锁全都一样的,因为每个人都是站在自己的屁股角度考虑问题,不会考虑别人感受,有很多人他认为我水平很高,所以使劲催我老师。

你讲快点,老师你讲多点,有的人呢实际上人家水平真真没到这个位置,我们呢稍微要照顾照顾基础稍差的,对不对,好了我,乐观锁为啥叫自旋锁,别着急啊,你听我讲完,你就理解了为什么叫自旋锁。

为什么又叫无所,好好听我讲啊,我原来只是就是讲cs的时候。

我没有单独的把它拎出来,今天我单独把它拎出来啊,今天上课之前我画的这个图,我们现在聊清楚什么叫cs,聊清楚cs,你聊清楚什么叫乐观锁,乐观锁这玩意呢,什么叫它就叫不上锁,那cs的全称。

我们平时说的全称全称叫compare and swap。

一会我敲吧,给大家敲出来,cs全称叫做什么呢,它有好几个称呼啊,所以我就说有的人呢追概念没没什么意义啊,叫compare and swap,叫比较并交换,或者说叫compare。

and set比较并设置,还有一个叫法叫compare and ex change。

就比较并交换啊,其实本质是一个意思,好听我说这句话是什么意思。

我们就来探讨一下,cs是怎么来保证一个值给它增加上来啊,给他那个加加,拿刚才那举例子啊,加上来之后还能保证数据的一致性,最后的结果还能得到100万,我们来举这么个例子,大家看这里啊。

这是原来那个值那个零,这是原来那个零,如果我有一个线程想对它进行递增的话,我怎么做呢,我不上锁,我首先是读这个零,把这零读过来,对它做加加变成一,然后再把这个一写回到内存里面去,这是整个过程。

这是佳佳的操作的整个过程,先读过来,读到哪儿去呢,读到县城这里,你简单理解读到某个CPU里面去,我刚才说了,每个线程在一个CPU里面运行,我读到这个CPU里面来,我给他做加加操作。

把它变成一再给他写回内存。

大概就这么一个东西,好同学们听我说。

关键的关键就在于往回写的时候,要做一个你写到这里啊,往回写的时候要做什么操作呀,要做一个CAS操作,这里cs指的什么叫compare and swap,这个操作相当于是这样的,我先做一个比较操作。

if看看您老人家这个值是不是依然为零,如果您老人家依然为零,我就把你设成一,大概是这么个意思,我再说一遍嗯。

首先读过来做递增,但是你往回写的这个过程之中。

他会做一个操作,它会首先做一个比较,这个比较比较的是什么东东呢,比较的是哥们儿,您这个值被我拿走之后,递增了的这个值是不是依然为零,仍然还是这个零,那如果你仍然还是这个零,我就要把你这个值变变成一。

能听懂吗,这就是cs操作,cs操作指的是当我设定一个值的时候,我首先做一个比较操作,那现在问题就来了,这个东西怎么能保证一致性呢,万一我设定的时候它已经变成一了,变成八了,变成九了,这时候该怎么办呢。

好看这里我这时候模拟两个线程来做这事儿,比如说啊我第一个线程,我把这零读过来,然后我做自增操作,我把它改成一,但是正在我做的过程之中,注意我没上锁,我可没有二话不说上那把悲观锁,我只是把它读过来。

做自增,我还没有来得及把这个零改成一的时候,另外一个线程读了这个零过去,把零改成了一把一给写回来,所以这个时候呢对于第一个线程来讲,这个值已经不再是零了,再看一遍这个过程。

这个过程是我左边这个绿色的线程,他把这只读过来,我正在做自动操作,还没有写回去的过程,有另外一个线程已经把这个零改回成了一,然后那么这个时候根据cs来做操作的话,同学们你们琢磨一下。

会判断这个值是不是依然为零,还记得吗,因为我刚开始读的时候,这个值是零,所以我要判断它是不是依然为零,那如果他依然为零,说明没有被人动过,我直接就把它改成一,对不对啊,VIP都没有看过这动画。

对我下午刚刚做的哈哈下午刚刚做的嗯,因为这个概念还是很重要的一个概念,所以我专门把它拎出来,那这时候怎么办呀,同学们,你们琢磨一下怎么办,他已经被改成一了,已经被改成一了,说明被别人改过了。

被别人改过了,我就重新再读一遍,听懂了吗,我就把这一读过来,我把它改成二,我再做CI操作,我判断哥们,你是不是依然为一。

如果你依然为一怎么办,那我就给你改成二,如果你已经不是一被别人改成八了,没关系,我再把八读一遍,读过来之后呢,判断你是不是依然为八是八,改改成九,不是八,没关系,我再读一遍,直到有一次成功为止。

所以你看看他像不像自选,所以为什么叫自旋锁,唉就这意思,为什么叫无锁,因为没有上那把悲观锁,不是上来之后我先锁定某个东西。

然后那个嗯喂喂喂,这个这个这个这个东西,你可以理解为他拎着裤子在这转圈就行了好吧,为什么轮到我呀,什么轮到我呀,锁开了吗,锁开了就轮到我,我就直接杀进去了啊,所以要自选所LINUX的原地转圈,自选。

还有同学说老师您说了半天,这个JOC里面确实是用到了吗,如果你要读GOC源码去。

一定它是用到了的,但是DOC源码你读起来比较困难,我快速的给大家管这块,你要听不懂,听不懂就听不懂了,没有关系啊,因为这块内容就就就就就就主要比较多,就JLC等等。

我们拿这个reentry log来举例子,就是听我说reentry log这东西,它本身呢嗯弄了一些个具体的实现啊,Nf,好看这里啊,你看给他上锁的时候。

Lock lock compare and set state,看到了吗,是不是cs操作,就是它嗯嗯所以呢你你你你就你就去看吧,就是所有的这些个JOC新的锁,本质上都是都是用它来实现的。

但讲到这儿呢,同学们听我说完还没有,完完全全没有完,你先把cs的概念给我消化掉,再说一遍,再看一遍这个动画你就了解了,就是总而言之,cs是怎么做到数据一致性的,不上锁的情况下做到数据一致性很简单。

因为我要改回去的时候,看看是不是被人改过了,没被人改过,我才改,有有被人改过,我重新来再看一遍,当我读这零过来的时候,如果中间被别人已经把它改成一了,这时候怎么办,没关系,我重新搜一再读一遍。

什么一直改成功了为止,好吧,OKOK这是cs最基本概念来掌握最基本概念的,给老师扣一,下,面我们来聊他的细节,里面细节很多啊,右边的进程不用cs吗,也是啊,我们假设是右边的进程成功了,改了这个值吗。

也是一样的,都是cs,好好听我讲啊,呃就是这玩意呢,这玩意儿有一个致命的问题。

同学们。

系列 5:P2:1、程序的栈(栈帧stack frame)和堆 - 马士兵学堂 - BV1E34y1w773

你可以在简历上写写啥,写这个叫熟悉GC常用算法,熟悉常见的垃圾收集器,熟悉常见的垃圾收集器,具备实际JVM调优实战的经验,就是说你听完今明两天的课,差不多有三四个小时。

就直接可以在你简历上写上这么一条来,不知道有多少同学能够意识到,当你在简历上写这么一条的时候,你这份简历可以多值多少钱呢,大三可以写吗,可以啊,没问题啊,这跟你大几没有半毛钱关系啊,可以出去吹牛逼了。

不用吹牛逼啊,这个是真正值钱的地儿,我告诉你3000块钱,至少你在简历上写这个,原来你简历值1万5,现在就值1万8,好看这里今天开始听我慢慢道来好吧,今天我主要给大家讲的到底什么是垃圾。

怎么定位这个垃圾常见的算法,常见的垃圾回收器,调优的实战,明天讲好吧,调优实战比较难,稍微复杂一些啊,说错了,其实那个实战相对容易,理论理论啊相对比较难,我们一点一点讲,放松了讲。

今天我也是第一次这么来讲,我怎么讲呢,我是从那个最底层的一个本质来跟大家聊,首先呢给大家几十秒钟,你扫一下这张图,看是不是能理解,嗯看满天只说工资才3000,没关系啊,听完就6000人要有梦想。

不然跟咸鱼有什么区别呢,好又是这张图对这张图几百年不变,只要是冯诺依曼结构的,冯诺依曼结构的计算机体系不变,这张图就永远不变,哪科都有张图,一周拿克,还有马老师的好看,这里嗯作为一台计算机来说,怎么样。

这个程序是怎么运行的呢,这里是QQ点EXE,平时呢它静静的躺在硬盘上,我想静静是吧,静静的躺在硬盘上,什么时候它执行呢,当你双击这个图标,操作系统老大会把它从硬盘load到内存好。

这个过程我们叫load,load到内存,漏到内存之后,这哥们会形成一个进程,Ok,会在内存里面形成一个进程,这个进程里面包括什么呢,包括一条一条的指令,一条一条的数据。

然后接下来CPU会一句一句的一条一条的指令,拿到自己的内部来开始执行,需要数据的时候再把数据给读过来,他真正开始执行了之后呢,实际上它还是需要内存的辅助好,这个进程的内部到底是怎么组织的呢。

好好听我讲这个进程内部怎么组织的呢,呃这块我就简单介绍到这,没问题吧,可以关注一下微信的声音哦,Sorry,你提醒了我,稍等片刻,好了,这下世界安静了,是怎么组织的呢,在这里呢我介绍程序的栈和堆的概念。

程序的栈和真,也许有同学了解过,也许有同学不了解,你认真听就可以了,呃我们来看这样一个小程序,这是我刚刚敲的,假如说啊我们自己写了一个main函数,main方法,我在里面是这么写的。

是object o等于new object,然后呢我第二句话呢,我调用了另外一个方法,这个方法叫M在内存里面到底是怎么运行的呢,听我说这就是这个进程里面的一个结构,这个进程里面结构是什么样的呢。

首先第一点,object o等于new object,这里面有两个东西,第一个是这个变量,这个小O小O在哪呢,它是位于我们的栈空间好,这里叫做站,只要是冯诺依曼结构的这样的一个程序,我告诉你啊。

它结构都一样的,这里叫做战战是什么意思呢,战战嘛,如果你稍微学过一点数据结构,就是先进后出,先进去的,后出来,后进去的,先出来,它是这样一种数据结构,你可以认为它就是一个桶。

你先把这个馒头扔到桶底下去的,你要拿的时候得先把上面拿出来,最后一个才能拿出来好,这是这个占空间,在占空间里面,首先呢会有一个战争出现,这个战争是谁呢,任何一个方法出现的时候,都会有一个战争。

任何一个方法都会有一个战争,ok main方法,main函数既然是调用main函数,那么首先在站里面会形成一个战争战争,它的英文叫STAFRAME,这叫做基于站的这样的一个一个一个结构啊。

其实除了基于站的结构之外呢,还有基于别的结构,但是基于站的结构啊,还有基于寄存器的结构,基于这样的结构是最常用,最简单的,最简洁的java就采用了这样的结构,java程序开始执行会形成会有一个站产生。

注意这个站呢一个县城一个站,每线程一个啊,你看啊,当我们呃程序开始运行的时候,这是我们的主线程了,我们主线程呢就会维护一个数据结构,这个数据结构呢就是一个站在这个站里面呢,它会生成这样的一个方法的调用。

方法的调用路径,这调用呢首先会生成我们的main方法的栈,当然main方法的站放到栈里面之后呢,叫一个战争,一个方法对应一个战争,如果说你比方说在main方法,执行到某一句话的时候。

假如说他是执行到这里了,这方法执行到这里的时候,它调用了另外一个方法,这时候会怎么办呢,会在这里暂停,然后跳到M方法里面去运行,当然这个M方法怎么运行呢,实际上就形成另外一个战争,就是这个M战争。

然后指令放在哪呢,指令永远放在最上面,那该执行哪条指令了,把这个指令呢拎出去是吧,然后他还有一个非常重要的特点,什么样的特点呢,就是如果一个方法执行结束了,比如说我M方法调用完了,M方法执行结束了。

或者main方法执行结束了,它会把它给弹出去,所弹出去是一个形象化的说法,其实呢就是把栈顶指针往下移动就可以了,栈顶指针往下移动,暂停指针往下移动,CPU要找的时候就会从下面开始找了。

就不会找上面上面就废掉了,所以这是站的一个特点,不知道我说清楚没有,这很简单啊,你稍微有一点那个计算机基础的话,一说你就应该明白,所以如果这句话。

object o new object它会首先在这个战争里,main这个战争里面生成一个小O,注意这是个小O,但是我们new出来object放哪呢,如果说这是我们new出来的object。

它是放在了我们的堆里面,这是堆空间,所以堆空间是在程序执行的时候,用来动态分配内容的空间,OK然后这哥俩之间建立一个关联,这个小O通过这个小O可以指向new出来的对象,好了。

这是大体的栈和堆的最基本的概念,那有同学可能就会说了,老师你这你讲这个是要不是讲GC的吗,怎么突然开始讲这玩意儿,因为这东西啊跟GC的发展呢叫做息息相关,好我讲到这,大家还能跟上吗,没问题的。

给老师扣个一,稍微做一下总结,就是每一个县城都会维护自己的县城站,县城站里面放着的是一个一个方法,调用调用的路径的一个战争的堆叠啊,就是一堆战争啊,M方法调了main方法调了mm呢,如果再调一个方法。

它就在上面再形成一个战争,什么时候这方法调用结束了,怎么办,啵儿往外一弹,所以有同学说了,老师那这两个有什么区别吗,好好听我讲,好好听我讲,老师这个站和对应有有什么区别吗。

这里面最重要的一个区别是什么呢,最重要的其一个区别是我不知道大家发现没有,作为占空间,当你占用了站里面空间的时候,它是自动释放的,OK我再说一遍,作为站里面的空间,它是自动释放的,这空间是自动释放。

为什么要自动释放啊,方法已结束,战争顶针啊,顶上那个格就往下移,你得找下一个继续往下运行的那个地儿去,你得跑到下一个战争空间里面了,所以上面那个战争空间就废了,直接就废了,自动释放有什么好处呢。

就是如果你有一些空间是分配在这里的话,你在这里面占的地没关系,你不需要手动释放它,你发现没有,你只需要说这方法一结束,哎哎哎它就弹出去就没有了,所以你发现没有这块空间,虽然说他也占一块空间。

但是呢你不用手工去释放它,没必要去释放它,什么时候释放main方法一结束,整个往外一弹就结束了,但是堆不一样,堆是什么,堆是在你执行过程中自己手工雕出来的,new出来了之后就会产生一个空间啊。

占了一块地方,你发现没有,那如果说你这个程序里头不停的new一个for循环,不停的往里new new new new new new new new new new new,你发现没有一个很重要的问题。

很严重的问题,这哥们儿很快这个空间就没了,是不是早晚就没了是吧,同学们,那现在的问题是你怎么去管理这块空间,占空间很简单,只要是方法一结束好,所有的占的空间就全弹出去,就没就没有了,你不用管,特别简单。

但是堆空间不行,堆空间是你要往里头分配,但是你得负责把它给回收,回收的意思是什么意思呢,回收的意思就是把这块空间标记成为可用了,原来呢是你是站着的,被别人给占住了,不能让别人用。

比其他程序不能用其他的语句,不能用,其他线程不能用,但是你必须得手工的来进行对它进行管理,什么时候呢,你觉得我用不着这个对象了,你就要把它给删掉,删掉就是做个标记,这块空间已经可以用了,已经让出来了。

不知道说清楚没有,听我说我这里讲的东西呢,跟任何的语言呢没有关系,跟语言没关系,任何语言,任何语言再强调一遍,从诞生到现在为止的,所有语言都会面临的一个问题。

系列 5:P20:20、ABA问题 - 马士兵学堂 - BV1E34y1w773

我们先说这个cs的第一个问题啊,cs有一个致命的问题,这个问题呢叫做就是凡是问到你cs自旋锁,乐观锁一定会问你这个问题,问题一,这个问题是什么呢,ABA问题,这是著名的著名的问题。

这个AABA问题是什么概念,其实很简单,就是同学们你们琢磨一下啊,如果我把这个一读走,然后我翻回头来的时候,做修改的时候,我判断诶哥们儿,你是不是依然唯一啊,唉确实他依然唯一。

但是这个一很可能在中间经历了一些别的事儿,怎么经历的呢,有可能有一个线程把这个一改成了八,另外一个线程把这个八又改回成了一,所以此一非彼一能听懂吗,再说一遍,ABA问题指的是什么呢。

在我修改这个值的过程之中,虽然我判断它依然为一,但是这个一有可能是从一改成了八,又回又八,回到了一,这个过程虽然看上去还是个一,但实际上被别人改过,这个东西呢叫做ABA问题,因为从1~8又回到了一。

这叫A改成了B,又回到了A叫ABA问题,来get到这个问题的,给老师扣一,当然咱们现在这个小例子呀,没别的问题,我们不在乎哈,简单直基础类型,你说这个一跟那个一到底有啥区别,没关系啊,没问题啊。

但是如果这是一个引用类型就完蛋了,这是个引用类型,中间指向了别的对象,后来又回到原来对象了,中间指向别的对象的时候,你这个属性改变了,其中的某个属性改了,那完蛋了,中间就有可能产生问题,能听懂吗。

所以这玩意就看你在乎不在乎,如果你在乎这时候怎么办,解决ABA问题,怎么解决JDK呢。

给你提供了各种各样的解决方案,好吧嗯,看我在哪讲的啊,On safe,看这里,比如说这种atomic reference啊,就这种东西是专门解决ABA问题的,Atomic reference。

如果你呃呃呃呃呃,中间有一个那个那个引用类型被指向了别的了,中间或者说它的属性变了,这时候就会产生ABA问题,那么怎么解决呢,它提供了两种方案。

第一种呢叫stamp reference standard reversion,指的是什么,就加个版本号,某一个内容被人改过一次之后呢,旁边还记录了一版本号,改一次版本号加一,改一次版本号加一。

如果你读的时候,这个版本号为一,回来的时候发现版本号为十,说明被人动过了,看你在乎不在乎,不在乎就算了,这是你的女朋友,这是你的男朋友吧,boyfriend好,然后你出差了。

回来之后呢发现依然是你的男朋友,但是你不太放心,你这个时候呢在他脑门上记录了一个版本号,你走的时候是1。0,回来的时候是99。0,说明什么,说明被人动过了,这时候就看你在乎还是不在乎,能听懂吗。

就是你回来的时候,9。0你该怎么处理,是你自己的事情啊,OK这个东西就可以理解为叫stamped reference,里面记录着一个邮戳版本号,当然当然,除了呃用版本号来解决之外。

还有一种这种叫markable reference,那么这种叫是什么意思呢,其实这种的呃用法呢是叫做用布尔类型来代表,简单说这是你的男朋友,在你离开了之后,他从1。0到了99。0,你这人的容纳度比较高。

只要100以下,我不在乎,OK那你就用这个就可以了,但是呢有的人一次都不行,你完全可以用布尔类型,走的时候为true,回来的时候为false,说明中间被人改过改我我才不管他改多少次。

改一次我都受不了干掉,所以两种一种是记录版本,一种是记录布尔类型。

详细的我就不给大家演示了,嗯好理解吧。

是不是很简单,所以ABA问题这件事情比较容易理解啊,要记一下。

A别问题的解决方案。

版本号或者布尔类型,Ok。

来这块儿能听懂的老师扣一。

系列 5:P21:21、CAS原子性问题 - 马士兵学堂 - BV1E34y1w773

这个AABA问题不是最难的,最难的是下面这个问题,cs的原则性问题,这是最难的,嗯解释一下这个问题啊,cs原型问题,问题二,这个问题的本质是cs操作本身必须具备原子性,这是什么意思,同学们。

你们琢磨这件事嗯,我们说啊,就是这个cs操作本身是这么一个东西,if这个值是不是我们期望那只,如果是我们期望这个一,那么我就要把它改成二,大概这么一操作,你们琢磨着这件事。

如果有一个线程执行到这里的时候,判断哥们,你确实依然唯一还没有来得及把它改成二,然后被另外一个线程打断,已经把它改成八了,最后的数据一致性就又没有了,我再说一遍,在做最后一步比较并且操作并且交换。

并且设置的这个过程之中,刚做完比较还没有来得及做设置,中间被别的线程打断了,那这个时候依然是实现不了,我们最终的数据一致性,也就是说这把锁本身就实现不了了,所以CAS本身的操作二话不说,必须保障原子性。

叫做中间不能被打断,这叫做原子,这一步是怎么实现的,听懂了吗,这是下面我们要解决的另外一个问题,也是大厂会问到的另外一个问题,OK来。

我们来聊一聊这东西到底怎么实现的,这件事情实现上呢相对复杂一点点啊。

我讲讲看看能不能跟得上嗯,我看有好多同学在那敲unsafe啦,这个啦那个啦,你说的很对,为了了解清楚这个问题,我们我们挑一个比较简单的吧,比如说atomic energy,本身这哥们也是用cs实现的。

大家都知道啊,就是atomic enager作为一个数值的递增,是不用上锁的,对不对,不用上锁,它就一定是用cs实现的,你放心,比如说啊,原来我们得上这把锁,Synchronized,我们现在不用。

我们只要用increment and get来做这个操作就可以了,好好好听,我说这会儿还能跟上吗,能跟上,给老师扣一,好看这里看这里,好多同学搁那敲volatile,还没敲,对你是几个意思。

你咋那么逗呢,这volatile volit,啊这东西还没敲,对你是什么意思,别敲了啊,丢不丢人,行又一个没敲对了,行不行啊,大各各位,我又又又没敲对,哎呦行了行了行了哈哈,好大家看这里啊。

我们下面就来探讨他这个cs操作怎么来完成的,注意看count点,Increment and get,这就是做了递增操作了,我们看递增操作是怎么做的,点进去好,有同学敲了unsafe,说明你们说的很对。

确实用到了一个类,叫做unsafe,Get and at end,咱们再点进去,在这里你会看到cs操作,这个cs操作是compare and swap int比较,并且交换什么样的值。

一个int类型的值,你再点进去,再点进去就完蛋了,因为这里是native,是本地代码的实现,本地代码实现的就是C和C加加代码的实现,那这玩意儿它到底是怎么实现的,我就理解不了了,我就了解不了了。

再看一遍啊,就是说如果我要用一个cs操作来做自增,我是不需要上锁的,它本身是怎么完成的,它是调用了increment and get,调用了unsafe,Get and at int,在这个里面呢。

我又调用了compare and swap int,好这个方法是谁的方法,是我们on safe这个类的方法是他的方法好,这个方法到底是怎么实现的,它是native,native是怎么实现的。

是用C和C加加实现的,那大家读C和C加加的demo,swap啊,好swap,Swap,Swap dumb,讲道理,Swell,Swell,你吓得我都不敢读了,确认一下啊,读了这么多年是不是读错了。

读错了,一定要承认错误,swap读音,Swap,谢谢谢谢啊,你说的很对对,是读swap,我读错了啊,对不起,跟大家道个歉,不读swap是读swap,Sorry,嗯谢谢这三人行必有我师啊。

那刚才是谁教我来着,Dom,谢谢DOM,Thank you,好我们回了回了哈哈,讲着讲着技术聊英语了是吧,嗯好compared swap,Compared swap int,好好听,我说呃。

这里呢就是native,native呢是用C和C加加代码实现,那么C和C加加代码能不能读呢,其实也能读,其实也能读,那个,当然这个要读起来就相对困难啊,因为为什么呢。

因为这东西呢就相当于是HOSPORT的实现,因为HOSPORT本身拿是拿C和C加加写成的,中间还有一部分汇编,我带大家读一读,能跟上就跟跟不上呢,你就当听故事好吧,呃我们有hop源码课。

这课呢就是相对比较高端的课,首先你得给他做好编译,基本上windows环境编译不了,得是在LINUX环境底下比较好做编译啊,我一般偷懒都在LINUX下做编译,但是windows呢你可以直接看到源码。

这个没问题。

源码呢我给大家打开了,记住在那个呃java里面的那个unsafe那个类,实际上在C加加里面有一个类呢是和它对应的,这个类就叫做unsafe,点CPP是C加吗,还记得我们刚才用那个方法吗。

那个方法叫compare and swap in,那么在C加里面呢有这么一个方法和它对应,叫unsafe,Swap and int,好,讲到这儿还能还能跟上吗,能跟上给老师扣个一。

不能的那个你你你哪哪没跟上,你可以跟老师说说一说好不好,我一会儿我一会儿讲完,我再来给大家复习一遍好吧。

就是总而言之这块你们带那个那个cs,大家应该都能理解,对不对,cs的操作本质上是怎么完成的,我现在在讲的这件事啊,就是CAS应该能理解比较简单的概念啊,不难,下面我讲的是cs是必须要保证原子性的。

这个我相信大家也没问题啊,我们捋一遍啊,就是我刚开始给大家讲了cs的概念,然后呢告诉大家,cs操作本身必须要保证原子性,不然这本他这个锁就不成立了,然后呢,下面我们来聊的是,这东西到底怎么保证原子性的。

怎么保障呢,我们通过源码一步一步跟踪下来,我们读JDK源码的时候,发现他用的是unsafe那个类的,Compare and swap int,结果发现读到这的时候它是native的,是不是。

下面呢我们就是跟到native c和C加加代码里来,去看看这哥们到底是怎么实现的,好了,是不是是不是跟上了,可以跟上了吗,嗯跟上跟不上我们就塌了,好吧啊,看这里啊。

这个代码去哪里找这么细节的问题,咱们后面再聊吧,open jdk的代码上网去找就行了啊,老师会教你怎么找我,教你怎么编译,编译还比较困难,看这里啊,就是那个当我们读到这段代码的时候。

这里呢就是C和C加加的对于compare,对于cs的一个具体的实现,它是怎么写的,特别复杂的,我就不带你读了,你就注意看就行了,在这里呢他调用了一个atomic这个类,这是atomic类的静态方法。

叫compare and exchange方法,我们直接给他直接给它定位过去就可以了啊,直接给它定位过来,中间过程我就不带大家那个跟踪了,注意看,总而言之言而总之,我们跟到最后会发现。

它的实现方式呢是atomic这类的compare exchange方法好,我们读这个方法的时候,你会发现它的实现是一个ASMSM的,全称叫assembly language,叫做汇编语言。

简单说这是个汇编,汇编的实现,好汇编是由什么来实现的,是由他来实现,注意看叫compare and exchange,我们讲到这,我相信你已经得出来第一个结论了吧。

来记一下cs原型问题,我们都是通过JDK代码跟到了unsafe,这个类里面的,Compare and swap in,后来发现他是native代码,所以我们跟到了unsafe的CPP里面。

又跟到了atomic这个类,这个这个这个有一有一有一个方法叫compare,And exchange,跟到了这里面好,跟到这里面之后呢,我们发现它是一个汇编的实现,它是汇编的一个实现,这个汇编的时间。

这条指令叫什么,叫compare and exchange,好我们讲到这的时候,我相信你应该了解啊,这个东东这是一条指令,这是一个CPU的指令,是CPU的汇编指令,好讲到这能给他能跟上的老师可以。

就总而言之,它的底层是由哪条一条指令来实现的,哪条指令呢,就这条指令,这条指令叫compare and exchange,所以我们说cs本身CPU就有原始的指令,来支持他好,我们得到了这个结论了。

这个结论我们就得到了就是cs操作,CPU本身有指令支持哪条指令,就是这条指令,但现在问题来了,这条指令它能保证原子性吗,我很不幸的告诉你,这条指令不保证原子性,也就是说,虽然你看到了这条指令。

Compare and exchange,不保障,保证原子性,所谓的不保证原子性是什么概念啊,简单说就是这样一个概念,就是这是我一颗CPU,这是我一颗CPU,如果我两个CPU都要改内存的同一块地址。

这颗CPU用的是cs操作,这个CPU用的也是cs操作,互相之间有可能被打断,这个可能改了一半,还没来得及收回去的时候,被另外一个C车打断了,所以总而言之,言而总之,这哥们儿跟到最后也没戏。

因为他不不支持原子性,我讲到这儿呢,讲一点扩展的概念,有同学会说了,老师一条指令是不能够是不是原子的,是一个什么概念呢,不是原子的,就是它中间可能会分成好多步,而且有可能被其他线程或者CPU打断。

很多同学在这块老犯糊涂啊,我稍微多讲一点点就多了,不讲就讲一点点,看这里就拿这条语句来说,很多人认为这条语句呢他应该是个原子的啊,我new了一个对象,还能有中间被别人打断吗,其实如果你了解的话。

大家都知道java的源码啊,是被会被我们反编译成为,那不是反编译会被编译成为class文件,class文件这东东呢,它实际实质上啊本质上就是java虚拟机的汇编码,看这里我们看一下他的那个生成的汇编码。

你就理解了,Show bad code,在这个方法里面,main方法好了,这是这一句话生成的五条汇编码,看到了吗,这就是这优化生成的object o等于new object,翻译成class之后。

它是由五条指令构成,new duplicate special store和return,你敢说你在执行这里面的过程中,不被其他人打断吗,不可能,所以,在讲的稍微远一点点,我们说java代码写了一句。

很可能翻译成class之后,它是五句,而class是不是得交给JVM虚拟机去执行啊,去执行的话,是不是得翻译成为本地的汇编语言呀,这个有可能是50G能听懂吗,所以中间绝对有可能被别人打断。

笑到最后的时候,每一句汇编语言是不是有可能被别人打断,这个东西要去查手册,要查手册,你得去查那个英特尔那手册,看看哪条语句是原子的,哪条语句不是,我讲到这儿呢,我们来读这段,再来读这段代码。

你会发现呢,这哥们他不是原子性的,不是原子性,它到底怎么来实现呀,这事儿就麻烦了,我看他前面的前面还有一个叫lock if mp,这个我就不展开了啊,这个lock if mp呢转一下也可以啊。

你看一下他那个那个那个那个定义就可以了,这是一个宏操作,这是加的里面的特有的操作,java里面没有啊,叫宏操作,那么在这个里面呢,lock if mp后面你会看到这条指令,这条指令叫lock。

我先说结论啊。

我先说结论,就是你刚才看到了这个东西叫lock if mp,然后后面跟着的是compare and exchange指令,那么这个log e m p的意思呢,实际上最后会演变成为什么呢。

lock这条指令compare and exchange,所以最终的我们的cs的实现,是靠这条指令来实现,叫lock compare exchange,讲到这儿呢。

有同学可能会比较比较比较比较比较有疑问,说老师这个宏操作是什么意思呀,同学们听我说mp的意思呢,我们先理解什么叫mp p呢,叫,好这是什么意思啊,就是多个处理器,也就是说你要有多个处理器的情况下。

前面给你加一条lock指令,如果你是单个处理器,这条lock指令不用加,所以这是我们最终的一个汇编实现,我讲到这儿还能跟上的同学老师扣个一,嗯OKOK不错不错,那好当我们了解了这件事情之后。

下面我们就来探讨,为什么这样一句话就可以保证原子性了,我们探讨来探讨去,我们说cs要让cs本身具备原子性,然后呢找到了unsafe里面的cs操作,找到了C加加里面的unsafe cc。

这个cs操作跟到最后发现它是一条lock,指的就是c compare exchange指令,但这条指令不能保证原子性,最终的实现是一个lock加上compare exchange阿米达,这来探讨。

以前老同学跟着犯糊涂,也老有同学问我,他这么问,他说老师我是多个CPU,前面要加logo,我单个CPU前面还用加lock吗,单个CPU不用加,但是我单个CPU也可以跑多线程啊。

我单个CPU compare exchange的时候不会被我自己打断吗,这个真打不断,你在自己执行一条指令的时候,还能把自己给打断,那我那你太牛了,你先把自己给打死,再去打死别人,在我跑步的过程中。

先把自己腿打折,那你太牛了,所以别在这上面反弧度,单个CPU是不用加前缀指令的好吧,只有多个CPU才可以才会加这条指令,那么这条指令本质上是什么意思呢,其实很简单,这条指令的本质讲一个最简单的实现。

叫做这颗CPU,其中某一颗CPU要对它执行CNI操作的时候,只要前面加了lock,相当于把总线锁定,这根线只让我用,别人不不让用,什么时候我把这个值改完了,这根线才放开,那其他CPU发现这根线被锁了。

他肯定就访问不了了,必须得等别人把这把锁放开,他才能去访问,所以就保障了原子性,所以cs本身在底层保障的原子性,是用lock来实现的,当然这是简单的说法,要讲的话还可以讲的更复杂一些,好讲到这。

我相信大家应该理解,讲了很多东西啊,应该理解什么叫高性能,应该理解高性能的两个方面,响应和吞吐,应该理解单机的这种要怎么样提高一点点性能,所耗费的苦心,原来都是悲观锁,后来产生了很多乐观锁。

看了很多乐观锁好,那那个应该理解呢,乐观所得本质的实现是cs,应该理解cs本身呢,是最后这条汇编指令叫lock compared exchange,应该理解这个了对吧,但是如果我们讲的更深一点。

这条lock指令实际上本质它有好多好多东西的,这条lock指令呢说一下啊,简单说一下,这块听得懂就听,听不懂就算了,这条lock指令优先,锁定,Catch line,优先锁定缓存行。

有优先使用的是缓存锁,其次锁定北桥信号,然后才锁北桥,到这就算了,就到这吧,到到上面就可以了,到面试面试,面试到这一步的时候,面试官基本上可以拎起来吊,吊起来打了啊,基本上到这面试官不会往深里再问了。

当然缓存行这件事情是另外一个复杂的东西,有时间我再讲给大家听好吧,那么这个时候你应该理解了哦,这是cs的本身,OK北桥坏过是吧,北桥坏过。

系列 5:P22:22、大厂提问:是不是CAS一定比悲观锁效率更高?什么时候用CAS,什么时候用悲 - 马士兵学堂 - BV1E34y1w773

好好我们继续啊。

现在我们继续提问题,听我说,带上提问,那个是不是cs或者说用的GOC的,那些新的新的锁,一定就比A管所,效率要高,什么时候用cs漏管锁,什么时候用,没关系好,啊哈哈不不是的,看你那对,凡是问你一定的。

他一定是不一定有点绕啊,就是凡是问你一定的,他一定是不一定多CPU用cs单CPU用悲观锁,你这个脑洞很大啊,啊大大壮大壮还不叫大壮,哈尔滨,我说啊这个肯定是不对不对,我们琢磨这么一个问题。

首先第一点呢不是说CNS啊,我们说效率就一定比微管所效率高,千万别这么认为,嗯然后也不是说所有的情况都一定要用cs,都一定要用JUC新的锁就不要用synchronized,不是我先告诉你结论。

在你应用新的锁之前,如果能用synchronized解决问题的,优先使用synchronized,先说结论,能用,Sing sing,Sing,Synchronized,解决问题的优先使用。

优先使用synchronized,听明白了吧,能用synchronize这些问题优先使用的,好为什么是这样呢,好好听我讲,我们考虑一个问题啊,就是什么情形之下要用悲观锁,什么情形之下要用乐观锁。

我举个例子,这是一坑,咱们说有人要西门吹雪,西门吹雪,在这西门吹雪,要进去,噗噗噗,啊心吹雪呢,要进去噗噗噗要干,要要要要干事好,我们说悲观锁就是上来,西门吹雪二话不说,谁也进不来,同学们,你们想一下。

如果悲观锁上去,进不来,那么如果再来人的时候,微笑来了,花奔奔来了,好在来人的时候,其他人会怎么办呢,其他人会排队,记住这是操作系统的处理,西门吹雪,如果在里面呆着,上了这把锁,其他人再来了,叫排队。

踏踏实实到旁边屋里给我排队去,什么时候到你们了,操作系统叫醒你们,这个东西叫操作系统的线程调度算法,目前最常用的叫CFS算法,叫completely fair strategy,叫完全公平算法。

这个算法相对还比较复杂,一般来说考LINUX内核的时候会考会考到它啊,我们先不管,就总而言之,你们先憋着,老老实实给我排队去,在队列里边等着,什么时候叫醒你,你再出来,OK这叫排队,这是悲观锁。

那如果乐观锁的情况下是什么样的呢,乐观锁的情况下,拎着裤子转圈,微笑来了,就在这儿转圈儿玩儿,转圈儿到我了吗,每转一圈都看一眼诶,到我没有啊,每转一圈都看一眼,到我没有啊,好了,同学们听我说。

也就是说我们得得出一个结论来,如果我们用cs转圈这件事是消耗CPU的,听懂了吗,CPU你要执行while循环啊,它是一个循环,每循环一次都要看一眼,每循环一次都要看一眼,所以他要消耗CPU。

但是如果我们用悲观锁的话,它是不消耗CPU,为什么,因为它直接进队列,等待什么时候轮到你,什么时候C我们操作系统才会叫醒他,所以现在的问题是什么时候用cs,什么时候被挂锁,是不是就很简单得出结论了。

如果说西门吹雪执行的速度特别快,两秒钟完事啊,两个毫秒就完事了,不便秘,旁边有人等的人还比较少啊,俩人等着转两圈就转两圈,没有关系,很快就轮到我了,但是如果西门吹雪执行速度特别慢,便秘一进去就半小时。

你在旁边等的人还特别多,1万个人拎着裤子在旁边转圈,就等着西门吹雪,所有的CPU时间全耗在这些个现成的切换上了,好讲到这里,大家是不是理解了,是不是cs一定比被光子效率高,不是什么时候,cs没有悲观锁。

就看你整个县城要执行多长时间,等待的线程的数量多和少,好了,那么既然讲到这的时候,为什么我们你能用synchronized解决问题,优先使用synchronized,您刚才不是说了吗,说判断具体情况吗。

我要判断我等待数量很少,我直接用那个新的锁不就可以了吗,同学们听我说,是因为刚刚讲的这个synchronized以前的实现,它就是用悲观所实现的。

但是呢最新的synchronized synchronized,自从JDK,1。5之后还有1。4之后忘了啊,反正总而言之,现在这个肯定没问题,synchronized内部有所升级的过程。

在SYNCHRONT内部,本身它是从偏向锁到自旋锁到重量级锁,可以这么说,你用了synchronize之后呢,它内部就帮你试了,自选组好不好使啊,不好使,我就自动升级成为重量级的,这个重量级的。

就是我们刚刚所讲的这个悲观派对所,我再重复一遍这个结论,按正常的情况下,有的问题我们要用悲观排队来解决,有的问题呢我们要用乐观转圈来解决,但是现在呢由于synchronized在最新的实现里头。

自己内部做了一系列的锁升级,它会优先尝试比较简单的锁,比较简单的锁,不解决问题的时候,会自动的去尝试重量级的锁,所以我们优先使用它,因为它的内部帮我们自己做了尝试了,好了,自旋锁就是轻量级锁。

就是cs就是无锁等等,说的是一个概念,冒个泡怎么着,你要排个序吗,冒个泡难道是排个序吗,偏向锁是个啥,我勒个去,这讲起来还有完吗,我任何一个点给你展开都是一堆问题,我看时间吧,几点了,建议百度。

你百度能看懂也是你的本事嗯,偏向嗬,这新概念又来了是吧,偏向锁是可重入锁,这样子就有新的概念了,就可重入锁的概念就出来了是吧,10分钟我看能不能讲完吧好吧,你讲到十点偏向锁,简单给大家介绍可以吗。

介绍完偏向锁,咱们今天的课就到这,那可以的话,给老师扣一嗯,好什么叫偏向锁,偏向锁其实挺复杂的,我跟你说,偏向锁可以说是synchronized锁,升级里面最复杂的一个锁。

这个锁呢我尝试用简单的语言给你解释清楚,但是大家听我说,里面好多细节我就在这就不展开了,什么叫偏向锁,偏向锁的概念是这样子的,然后打开PPT好讲一些。

等会啊打开另外一个PPT。

嗯嗯这个这个这个这个这个这个图。

主要画起来比较方便啊,习惯用这个图。

而且我说所谓偏向,我们说所谓重量级锁是啥意思。

重量级锁的意思是上来二话不说把这锁定,然后进去进去里头干活,那么呃自旋锁的意思是看见被别人锁了,我就自己在这转圈,那么偏向锁是什么意思呢,记住偏向锁是应用于第一个线程,仔细听认真听,先把这结论给记住。

所谓偏向是应用于第一个线程,比如说第一个过来的人,他上的这把锁偏向锁,严格来讲,偏向锁不是一把锁,他就是一个标签,好好听我说,比如说有一哥们过来了,西门吹雪,他第一个过来,所谓给门上锁。

就是把他的名字直接贴在上面,上书四个大字,西门吹雪,好了,这个东西就叫偏向所有同学说老师好简单啊,这个东西你还你还把它搞得那么复杂干啥,其实很简单,我们说通过专业角度来讲呢,就是说第一个县城来了之后。

把自己的线程id记录在对象的脑袋上,Object header,我们刚开始最开始讲的那部分object header还记得吗,里面记录的锁信息,就是把自己的线程id记录在脑袋上,说这锁归我了,好吧。

这就这东西叫西门吹雪,但有同学可能就会说了啊。

说老师这事儿不对呀,当然这个东西要了解的话呢。

得把这张图给他,你自己抓下来吧,就是所谓的偏向锁呢指的是当前线程指针啊,相当于你把当前线程的id号给记录在脑袋上,好吧,然后呢,他用几位几几位来代表不同的偏向锁的状态,是这意思啊,反正总而言之。

言而总之就是往上一贴就表示这把锁归我了,可是这个时候问题马上就来了,说这把锁归你了,那我后面再来人的时候怎么办,后面再来人的时候,凭什么这把锁归你啊,对不对,上面写着吹吹吹弦,你就你就随便吹啊,马上了。

五成五常大米就来了是吧,我大米还想往上贴呢,对不对,凭什么就归你,那我再来人的时候怎么办,记住再来人的时候撤销偏向锁,把他名字给撕下来层,然后呢,大米过来自旋升级为自旋锁转圈好吧,大米又来了啊。

这个欢乐马又来了是吧,欢乐又来了,大米跟欢乐转圈来,咱俩开始转圈,已经升级为自旋锁了,那我讲到这儿呢,有同学会觉得非常的奇怪,说老师啊,为什么会有偏向锁这个概念,您上来自选不就行了吗,为什么要偏向呢。

同学们听我说啊,就偏向这个概念呢,它设计上比较复杂,而且呢JDK15已经把它废了,比如说JDK15,你要用JDK15以后的偏向锁,这事你就可以把它忘了,因为它太复杂了,它复杂在哪呢,为什么要设计偏向锁。

这个大家还能听吗,还能跟上吗,可以是吗,为什么要设计偏向锁,这是最难理解的,偏向锁为什么要设计它,是因为在大多数的根据工业统计,在大多数的情况下,所谓的上锁那些个方法往往只有一个线程,只有一个线程在用。

啥意思,我给你举个例子。

有一些吧,我们那个那个那个累累,你们就算没用,也应该听说过,比如说,Spring offer,这应该听说过,比如说vector,这应该听说过,对不对,好同学们听我讲这些个类呢。

我们点进去看它里面好多好多的方法啊,它里面有好多好多方法,就比如capacity吧,你会发现它的方法本身就是自己就上了锁了,叫synchronized,本身就是synchronized。

Synchronized,对不对,所以当我们用这些个类的时候,就算你自己没上锁,实际上你自然不自然的呢,你已经在应用锁的一些操作了,那现在问题就来了啊,那个真的我们用string buffer的时候。

它会产生锁定征吗,就是好多线程会同时在执行吗,不一定的。

根据工业统计的结果呢是七八十%的时间,记住七八十%的时间,实际上只有一个线程在那里跑,听懂了吗,只有二三十%的时间,是有多线程在那里竞争,那为了这七八十%的时间,您老人家有事没事还上悲观锁,他合适吗。

肯定不合适,所以为了这七八十%的时间,我干脆呢我们就来一个标签锁就行了,你上来二话不说,先贴标签,反正你七八十%的时间,只要看见了标签,就我一个人用,我就不用有所竞争过程了,没有锁竞争了。

就我就不用考虑这个锁竞争过程了,所以设计出来了偏向锁,好偏向锁这概念能get到的老师扣一,10分钟左右,但是我们说偏向锁超级复杂,并不是这么简单的啊,偏向锁本身呢有一个上锁时间,有一个JVM的调优。

有一个锁的撤销,有一个批量所撤销和批量重偏向,这个是面试里面最复杂的一部分,就到这吧好吧,毕竟我们不可能一天一个晚上,把所有的东西全讲完,那也不太可能你也消化不了,cs有哪些应用啊,那个那个那个那个。

为啥叫偏向,因为因为偏向第一个线程啊,我就偏第一个线程,今天还讲不还讲啊,明天我们继续可以吗,嗯嗯掌握了这些是不是可以吊打面试官了,你掌握这些了。

他只要问到这些。

系列 5:P23:23、JUC五花八门的新锁 - 马士兵学堂 - BV1E34y1w773

JUC的新锁啊,我们来聊这个这个东西。

嗯这里面其实有好多好多东西了啊,我先给大家介绍一下。

就是所谓的锁是什么东西。

就是原来我们想给某一个东西,给线程做同步,给某个东西上锁。

我们一般是用这个关键词,这个大家应该知道叫synchronized,但JDK1。5之后推出了很多很多的新型的。

所弥补了很多synchronized的不足之处。

呃这东西包括哪些呢,我给大家列几个啊,就比如说啊。

我们可以用and atomic相关的一些各种各样的类,atomic相关的包括什么呢。

呃这个就太多了,大概十几20个就是atomic。

什么integer是吧,Atomic long,atomic bullet等等等等等等。

就是那些基础数据类型在这全有啊。

atomic double等等,当然还有什么呢,还有atomic,比如叫reference,这是什么呀,这是用原子性的来呃。

Reference reference。

用原子性的操作呢去更新引用的是吧,当然还有带版本的。

为什么要带版本呢,因为这里面用到的全是cs操作。

这个东西叫atomic。

Stamped reference,当然还有那个简单的版本号啊。

叫atomic markable reference是吧,还有什么呢。

atomic更新,我们的用原原子性的来更新,我们自己的一个成员变量的属性的嗯。

Atomic field。

啊等等等等。

这个非常多啊,来这块需要我详细的需要我说吗。

我觉得这个应该应该不用吧,这个应该是是是是是嗯,比较简单的一个内容啊。

嗯JUC是啥是吧,对JUC是啥呢,JUC呢是这个叫做java,detail can current这个包啊。

这包下面所包含的一些新的锁。

大家平时写程序,写线程的时候,说给县城上上个锁。

怎么拿拿什么上,就是synchronized,但是synchronized它本身有好多的局限。

另外呢它用起来也不是特别灵活,不能适用所有的场景,或者所有的场景用起来写起来特别复杂。

但在这种情况下呢,嗯在DK1。5之后,JUC添加了很多很多新式的。

各种各样的花样的锁,这个也是面试的超级的重灾区。

我跟我跟大家说一下啊,这是超级面试重灾区。

就多线程这件事。

多线程这件事,基本上就是超级面试的一个重灾区啊。

我先把这块先给大家列出来,列出来之后呢,我们慢慢的在跟大家聊。

下面还有什么,比如说还有什么呢,嗯各种各样的新的锁啊,比如像替代,比如这个reaction lock是用来干嘛的呀。

替代,在在某些情形下啊,替代synchronized。

部分场合替代synchronized是吧。

还有什么,比如这个latch。

这是门栓是吧。

比如还有什么嗯,Semh。

这个是什么呢,这个叫信号量,这是N个N个现成的限流。

哈哈你可以这么来理解,比如啊还有什么呢。

嗯大家知道的可以跟我说一下啊。

你们可以敲敲试,上次面了一个10年的java,只会搞CRUD。

那好吧,比如CLI,cyclic barrier是吧嗯,这是什么呢,就是栅栏,比如什么呢,还有什么HASER,这是阶段同步器。

比如还有什么lock support。

这个是用来替代什么的呀,这个是用来替代我们的weight。

Wait notify。

用来替代这个的synchronized。

Wait notify,Synchronize them。

Which notify。

这是最早开始的时候,做线程同步必须要掌握的机制。

不能叫老的,这叫经典同步机制,是吧,还有吗,比如EXCHANGER。

这个相当于呢就算是一个嗯交换器啊。

让它同步同步交换器。

嗯比如还有什么呀,嗯嗯差不多了啊,差不多了,就是现在JDK自带的大概也就也就这么多了。

除了JDK自带的之外。

就说这些个新的玩意儿啊,是靠什么东西写出来的呢,这新的玩意呢你听我说啊。

两个东西啊,CKCS和EQS就这两个概念搞清楚了,你的心的锁就能透彻理解它的原理了,cs加上AQS这两个概念是什么概念。

就是说同步锁的原理,新型同步锁,原理包括哪些呀,原理就包括两个大项就可以了,cs啊,加上AQS,当然肯定要加什么volatile了这一类的啊,这个因为相对简单。

cs是什么cs呢,就是,Compare and swap,乐观自旋锁,乐观锁是吧嗯。

呃用户空间,解决问题啊,那个怎么能用文件,就是JVM自己解决问题,这版本自身解决问题啊,他是不需要。

操作系统老大的调度自己就能调度了嗯。

AQS是什么呢。

AQS叫做写这些锁的最根本的一个工具。

一个基础的类库,这里面还涉及到一个设计模式。

这个设计模式呢叫template method,如果你跟那个面试官要聊到这种程度啊。

我跟你说想要个什么30万50万的,你要就是了啊。

它叫做abstract,Synchronizer,Abstract cute synchronizer。

这东西是一个基础的同步器。

这么来理解这个玩意儿。

由他是可以写出来这种各种各样,各种各样各种各样类型的锁啊。

这些锁的最底层的核心都是他,那么你通过他呢也可以。

你自己想想,自己写自己这种类型的锁也可以的啊。

你想说那个只能两个两个执行,只能是三点执行。

像这一类的索尼完全可以可以用它来做,门栓等于门栓,你说的很对。

嗯正式版刻的多线程看起来太麻烦了,这个没有办法呀。

我跟你说多线程就是它本身呃东西比较琐碎,然后你还面试面来面去,面来面去,必须得做一些,我在第二版里头,会会帮大家做一些更深入的总结,会更会稍微爽一些啊,嗯大概呢基本上就就就就这么多东西啊。

就是新鲜的,我们今天看吧。

系列 5:P24:24、常见的Atomic CAS锁 - 马士兵学堂 - BV1E34y1w773

呃先讲一点比较简单的,像这种atomic,听我说啊,atomic这个东西叫做原子更新,我先讲点入入入门性的东西啊,就原子更新是个什么概念嗯,atomic atomic integer吧。

我们来看这个小例子就行了,比如设计最简单,有多线程啊,对一个数字往上往上做递增,那么大家应该都知道,如果你不上锁的话,这个数字最后得到的结果一定是不对的,但是不上锁也可以。

就是不上那种老的那种synchronized的锁,其实也可以用什么来做呢,用atomic integer或者atomic la,那么它里面的操作呢,这个东西是可以具备原子性的,它是具备原子性的。

Increed get,他为什么不具备原子性呢,当我们点进去它的时候,你会知道看一眼这里他用到了底层的一些操作,好这些操作主要的操作是什么呢,就是这个操作这个操作叫compare and swap。

In compare and swap,就叫做CAS操作,就叫CAS操,作,好这个cs操作呢,因为这种这个课呀我大概讲过好多好多遍了,我就是稍微给大家复习一下,有多少同学是不了解cs。

我要简单给大家介绍一下CAS,吐着天线宝宝是吧,好不知道cs的小伙伴啊,我大概快速的给你们介绍一下这个概念,先去了解它,think没调汇编指令,哪个都会调汇编指令好看,这里你像原来的话。

当我们对这个数字进行一个递增的时候,比他原来是一给他做一个加加操作,我们就给他上把锁就可以了,锁定啊,这个锁不好画是吧,哎这是一把锁给他锁上,咔嚓给他一锁,然后在我做这个操作的过程中,其他线程不许打断。

我持有这把锁的线程才有权去做加加操作,这是一种这种其实叫悲观锁,叫二话不说,我先给你,我就认为你中间有可能会打断我,所以二话不说我先上锁,而CS操作是一种乐观锁,CAS操作是乐观锁,乐观锁是什么概念呢。

看这里啊,他原来是个一,我这线程呢就把它拿回来,拿过来之后给他改成二,然后往回写的过程之中,这个时候做一个cs compare比较比较什么呢,比较一下哥们,你现在被我拿走的这段期间有没有被人改过。

我乐观的认为你不会被人改过,你依然还是那个一再说一遍啊,就是说我把这个一拿走改成二,再往回写的过程中比较一下哥们,你是不是依然还是那个一,您没变,如果我看一眼啊,您这个值现在依然还是那个一。

那我就把你改成二,这叫做比较,并且设置,那有同学说老师这东西没上锁,它能保证原子性吗,可以保证的,你琢磨琢磨这件事,如果你你你往回写的过程中发现哎哥们,你确实依然还是那个一是吧,那我给你把它改成二。

这不很正常吗,那说明你没被人动过呀,那现在问题是呢,如果被人改了怎么办啊,这这块还能跟上,对不对啊,如果被人被人改了怎么办,如果被人改了,比方说他也改成八了,那没关系啊,就把这八拿过来。

八拿过来改成九对吧,加加嘛加加操作,把九往回写的过程中比较一下,哎哥们儿,你是不是依然还是那个八,如果你是八,把你改成九,如果你是80,没有没有没有被人改过,是吧,这块能跟上啊,有人说了,又被人改过了。

改成12了,没关系,把12拿过来改成13,反正往回写的时候我都比较一下,看看哥们儿,你是不是依然是我期望的那个纸,来这块能能get到的老师扣一没问题吧,当然cs呢有两大核心问题。

cs有两大核心问题的重灾区,第一个最重要的核心的问题呢叫做,如果说你离开了,把这个一拿走改成二,返回了头来的时候,看到的确实是这个一,但是此一非彼一,很有可能这个一啊在你拿走改成二的过程中。

被另外的线程拿走,改成了八,后来又被别的线程把从又从八改回成了一,所以它中间有一个1~8到一的过程,虽然你看到的是这个一,你你读的最开始独走的是这个意义,但是实际上这两个一本质上是有区别。

因为中间经历了一个状态,这个AABA问题,这个问题是必须你你面试要对答如流的好吧,ABA问题,ABA问题,第一个呢看你在不在乎你女朋友离开,你经历了别的男人,当你回来,你发现还是他,但此他非彼。

他就看你在不在乎,如果你不在乎的话,就像这个一这个一跟这个一有啥区别,你不在乎不在乎没有关系啊,那就放过他吧,也放过自己呃,直接该怎么操作怎么操作就行了,那么如果你比较比较在乎你怎么做呢。

这个时候用的东西呢叫做叫做atomic reference,也叫做atomic stamp reference,stamp的意思是加个标记,加个标记,Atomic stamp reference。

你要拿它的时候,需要拿版本号的,知道吧,就是你需要你拿它或者往里设置它的时候,需要设版本号,比方说最初始的版本号是零,那么每一次都会往上递增,initial step等于是零,每次都要往上递增。

经历过一个男人脑门上写了个一,再经历过一个写了二,再经历过一个写了三,当你回来看脑门上写了1万,你就知道中间经历了一些事情,就看你在不在乎了,好吧,你要在乎的话呢,脑门上贴版本号来这块概念能听懂的。

给老师扣个一,嗯嗯明白这件事情之后呢,我们再来琢磨一件事,如果有的时候我只在乎改过或者没改过,动过或者没动过,而不在乎说到底动了多少次好,这个时候怎么做呢,也可以用另外一种呃加版本号的东西。

这种版本号的东西叫什么呢,叫MARKABLE,叫atomic markable reference,而这东西呢你只要说初始值给他一个false,只要有人改了,它就会它就会变成true了。

所以当你回来发现脑门上原来写的false,变成了true啊,说明你女朋友已经是真正的真正的女人了,是不是就这意思啊,至于说多少多少多少个或者多少次,你不在乎,你只要做一个布尔类型的标记就可以了。

这是另外一种解决方案嗯,当然代码那我就不给你详细看了,其原理是非常的简单的,你明白了原理之后,看代码就比较简单,所以我刚才讲了两个东西啊,第一个是cs的概念,第二个呢是。

cs所带来的ABA问题怎么解决好,我们现在来聊第三个问题啊,第三个问题我就不想细聊了,因为这东西我要讲起来一个小时以上,就是好好听我讲啊,你你琢磨琢磨琢磨这件事,就是在你比较并交换的时候被打断了。

怎么办,刚才我看有同学已经问出来了,还会还是说这个问题一咔咔咔咔咔哎,变成二二,写回去的过程呢,大概用维码来模拟的话,就是这样的啊,看看哥们儿,你这个值是不是依然等于一呀,如果你等于一的话。

我就把你设设为二了,实际上就这么一个操作,这个就是cs操作,如果不等于一,没有关系啦,来继续下一步了是吧,再重新读了,OK那好,这就是cs操作,但是你们琢磨琢磨过没有。

如果有另外的线程在这里把这两部分给打断了,我刚判断完V等于一,还没有把它设为V等于二的时候,另外一个线程把这个值直接给干掉,干成100了,结果您老人家把这100直接给设成二了,这肯定不是你想要的结果呀。

这块能理解吗,所以呢你要想完成CS操作,就是这里的操作必须要保证原子性,必须要保证原则性来并发编程三大特性,请给我读,并发编程三大特性,可见性,有序性,原子性,抽烟喝酒烫头。

当然这个东西的人是怎么保障的,这个东西的保障在于硬件的底层给你做了保障,我以前对这个呢做过深入的剖析,今天咱们主要讲应用层啊,咱们稍微放过自己,因为有好同学呢说老师,你这个公开课讲的有点难。

能不能来点简单和轻松一点的,完全没问题啊,咳,好嘞我我我就讲完cs的几大问题了,就说了cs的概念,ABA问题,硬件底层保障,原则性,听懂了吗,OK要喜欢男的是吧,那你肯定是女的了,水煮鱼啊。

那不是两个版本吗,你要是嫌嫌琐碎,你就你这个真是难伺候,我发现咱们学生真是真是难伺候啊,这个你知道为什么吗,因为有的人啊,他在腾讯课堂看的时候,他说一个版本一节课大概两个小时哇,老师我找东西找不着。

你知道吗,我中间讲了好多概念,我要拖动才能找到,然后我们第二版,剪成一段一小段一小段的,一小段一小段的,那你捡起来那个找起来就特别好找吗,水煮鱼说太琐碎,你锁什么叫琐碎,就是你找东西不更好找吗,水煮鱼。

我说大哥太难伺候了啊,别这样,你要是嫌那个什么去看那个腾讯课堂第一版,就你事儿多,不是不是不是这个意思啊,就是说呃我们呢是在做出努力,让咱们的VIP学员呢会更加的学起来,会更加的怎么说,体验感会更好。

别介别介别介,嘿嘿嘿停停停,就是我觉得啊我觉着我觉着小段比大段好,这是我的感觉,小段你可以选择,你可以选择听到这我就暂停了,我我我我一看标题,我就知道到哪了,大段的话呢不太不太方便啊,清晰明了。

而且他他就算在所说他有大的标题啊,大哥我是大标题下面的小标题。

咱别这样啊,你是我们VIP吧,确认一下。

这件事情是一堆的,我是大标题下面的小标题啊,这个这个这个看起来不更方便吗,德院长的第二版,这看起来不更方便吗,我现在正在更新,你像我这还有是吧,有大标题还有小标题,你找起来不更爽吗。

怎么会怎么会不如那个那个那个大段的呢,大哥,暴露了啊哈哈嗯好,我觉得这个体验应该会更好啊,大多数人应该会喜欢这个体验,来好了,我们继续啊,这里面所有用到的东西,基本上就是刚才我所说的cs。

系列 5:P25:25、都是锁,为啥JUC就比synchronized牛一点儿 - 马士兵学堂 - BV1E34y1w773

还有我说了啊,我今天讲的东西呢偏应用一些呃,我不知道有多少人不了解这个旧的锁是什么,是什么机制,就是经典的这种同步机制,不能叫旧的,叫经典同步机制,Synchronized。

还有wait notify这种这种同步机制,这个大家应该应该应该都了解是吧,Synchronize,如果要细聊的话呢,那里边的问题讲四个小时差不多,有各种各样的应用级别的细节。

还有各种各样的底层原理的细节,我们呢今天主要来聊应用,关于关于synchronized,我大概写了十几个程序来帮你解释,SYCHRONIZED是什么意思呃,Synchronized。

当我们这么来写一个东西的时候,叫synchronized的O,那这小O代表什么,代表的就是你上厕所的时候持有的那把锁,这个跟你下面的操作没有直接的关联,synchronized小O下面一堆操作。

这代表什么呢,代表当多个线程去执行,都是执行这段代码的时候,同一时刻只有一个线程在运行,这叫互斥锁,互斥,我再说一遍,我就就就这块儿,大家伙应该应该是比较熟的啊,这块要互斥锁。

就是synchronized后面跟了个对象啊,甭管它是什么,就是这个对象被我们当成锁来使用了,你就想啊,我要进厕所,我肯定得把门给锁上,门上那把锁就是这个对象,这是synchronized的本质。

然后synchronized上完锁之后,下面会进行一系列操作啊,脱脱脱脱脱裤子坐下解手是吧,OK然后然后穿裤子啊,完事好,然后一系列的操作好,这一系列的操作是必须持有这把锁的情况下,才能够进行。

那么这带这是什么意思呢,这把锁叫互斥锁,互斥锁的意思是只能有一个县城,同一时刻,同一时刻只能有一个县城在执行下面这段操作,只有这个线程把下面这段操作执行完毕之后,另外一个线程拿到这个线程。

执行完之后的最新状态才可以,执行同一段代码,申请同一把锁好,这个线程执行完了才是下一个线程,所以这会把并发的问题做成序列化的问题,所以互斥锁的本质就是,这互斥锁的本质,就是把并发的问题改成序列化执行。

独占yes,那么如果下面呢就是这个护士所呢,只能有一个线程执行吧,如我可不可以有两个线程啊,可不可以有三个线程呢,OK如果允许多个线程在里面同时执行,比如N个一共有1万个线程。

只能允许十个线程在里面同时执行好,这个东西就叫信号量,叫sam for,这就是心锁之一,并行改穿行,Yes,miss那片海同步锁呢,这个就是同步锁,互斥锁就是我们俗称的同步锁,同步锁是同步的概念。

是由各种锁都可以做同步,像这些个都可以叫同步锁,只不过我们有好多人呢,就约定俗成的不去那个细究概念,就直接说啊,synchronized叫同步锁,好嘞,最基本的概念呢synchronized。

最基本的你搞清楚了,weight是什么意思,notify又是什么鬼,这个我不知道大家有没有同学知道,weight是什么意思,NOTI又是什么鬼,等待啊,等待的本意一定要理解清楚啊,嗯像这个小程序啊。

我们有我们把这个object当成一把锁,我们有一个线程持有这把锁,打印启动睡一秒钟,让他去wait,让他去wait,注意有很多人呢把这个weight理解成为O点weight,这意思是说让O去WEIT。

让O去wait,大错而特错,嗯讲点最基本的概念啊,跟大家说清楚,不是让O去WEO是什么呢,O是那把锁,你要进厕所了,你要锁定那把锁,让所谓的O点weight哎指的是什么呢。

一直打完结束在O上面wait又错了,还是不对,OOOO点weight指的是什么,认真听指的是在这把锁上面,其实他持有一个队列,同学们,你们琢磨一下,由于一个时刻只能有一个人进去拉屎。

那其他人拎着裤子在旁边轮不到我的时候,该怎么办好,这个时候我们可以调用锁点weight,指的是A索大人,请你把我安排到,等待着这把锁的那个队列里面去,包括这些啊,这哥们全是等待的,在里面等着等着干嘛呀。

排队吗,排队排着队,等这哥们儿出来了,下一哥们进去,这个叫O点weight,所以O点weight的前缘,这个全全全全面比较精确的描述叫什么,叫在这把锁的进入这把当前线程,让当前线程啊。

当前的线程当前线程是什么呀,不就这个线程吗,new new了这个thread吗,让当前线程进入到这把锁的等待队列,等待着被调度,来这块能get到的老师可以,liquid嗯,ADAMS拉库里是吧。

等待调用,那好读音,比如说嗯这把我当前线程进入等待队列了,等待队列有一个很重要的特点,就是我不用再占用CPU了,这话能听懂吧,嗯所以这个是嗯,老的这种这种这种或者经典的这种同步的机制。

让O点weight weight的意思,我进入等待队列了,我就等着,我就等着调度器,老大什么时候把我调出来,我就开始来持有所进行了,我就不用消耗CPU了,已经持有锁了,为啥还等好这部分呢。

叫持有所持有锁的时候,比如说啊我给你举个最简单的例子,我要通过网络上读过来的一段数据,我才可以给他反馈回去,好这个时候我在等数据的过程,我有必要占用CPU吗,没有必要进入等待队列,等着别人把他唤醒。

这是第一种啊,再再给你举一个更经典的,比如说这是一个容器,我们有十个生产者往里头不停的扔馒头,我们有一堆的啊,我们有十个十个拉粪者往里头不停的拉粪,我们有一堆抽粪器,从外往外不停的抽。

那么当你拉满的时候,你必须得给我去wait,能听懂吗,必须得给我去wait,你不能说还往里拉,这玩意儿它就冒出来了,好昨天吃的虾仁你都能看见了,这肯定不行,所以这个时候在某些特定的情况下。

这个线程必须得wait wait,Wait,Wait,Wait wait,等什么呀,等什么,不就等着说那个抽粪器把它给抽,抽完了吗,抽完了你再继续吗,在这块能get到的老师口音。

哎所以一定要是要进入wait持有所,为什么要wait持有所,在你干活的过程中,有可能是需要等其他资源,所以你必须得要去wait gun,是公开课吗,Yes si,那这个代码不是死循环了吗,一直持有。

一直等,哎,你说的很对,听我说啊,weight是要释放锁的,所以呢weight这件事是释放锁,释放暂时释放,等他下次再回来的时候,他又被叫醒了,他会继续往下执行,他不会说从重新再把这锁申请一下。

它会继续从这里往下,哎来琢磨琢磨,还有其他问题吗,HY公开课吗,对公开课嗯,好嘞,所以呢这个wait的含义,我相信大家就能明白了,但是wait wait,如果你不指定的话呢,它是无限期等待,你。

不是等着操心老大去调调度他吗,去等着去调度他,那好什么时候把他叫醒呢,好听我讲,你可以在另外的县城里,比方说我这是我的主线程,我睡了五秒,持有这把锁把他叫醒,欧点notify啊。

older notify的含义,你明白了什么叫order weight,O点weight是叫醒进入这把锁的等待队列,等待被调度,Oder notify,叫醒某一个县城来,你醒过来了,赶紧去干活。

干活干什么呀,继续往下,抢到这把锁,继续往下,唤醒之后有锁定证,对你说的非常的对,这个大家伙考虑的细节考虑的比较多啊,确实非常的对啊,辣椒说的非常对,这个线程进入到等待队列了,在这等着。

如果有其他人把他唤醒,唤醒之后,他也是需要抢这把锁的,也是需要抢到这把锁才能继续执行,如果没抢到怎么办,如果没抢到,你程序自己处理,听懂了吗,如果没抢到,你,比方说你可以用while来写。

我们一般来说面试中的重灾区叫做生产者,消费者问题,生产者消费者问题里面一般是well,如果我醒了之后没抢到怎么办,我又又wait,我醒了之后又没抢到怎么办,我还是wait,唉,什么时候我醒了之后抢到了。

我才继续执行,所以用一个while循环在这里就可以了,怎么唤醒指定的县城,你说的真的是哎蚂蚁,你们这么聪明呢,我从来没有教过这么聪明的学生是吧,国企里8K还能杀到阿里拿个25好听,我说嗯。

既然大家说到了呢,咱们就再聊点细节的概念,首先第一点呢这个东西啊它是不消耗CPU,暂时释放锁,那么刚才我讲过cs,cs和这个的区别是什么,回想一下cs是怎么做的呀,cs是哎哥们儿。

你这把这个一你你你你你拿过来,他我拿过来之后,如果发现别人已经在改了,我不会去wait的,我会在这里转圈,哎哥们儿,你是不是还是一,如果不是U,赶紧读过来再转一圈,赶紧读过来再转一圈,cs叫消耗CPU。

一直占用CPU,听懂了吗,一直占用CPU,OK他不需要去调度,因为他永远都活着,所以他一直占用CPU,他不释放锁,当然他也没有锁啊,它本身就是自旋嘛,他没有没有那种原始的这种锁,CI就是所谓的自选。

严格来讲这两个概念是有一些细节区分,但是你完全可以这么认为,没问题的啊,就cs自选,一般来讲自旋cs是自旋锁的一种实现方式,但是基本也就这种,没有什么其他新鲜的,这个是阻塞了,对这里是阻塞了。

这个weight是阻塞了,而而那个阻塞的概念是什么概念,就是我把这把锁暂时释放,我去等着等着被唤醒,而那个cs是我永远都醒着,我就拎着裤子转圈,形象点理解这哥们在这里干活呢,噗噗噗噗噗在这里拉呢。

那么其他持有这把锁,其他人怎么办呢,如果进入到等待队列,老老实实等着这个东西就是weight好,如果那个那个那个不进入等待队列,拎着拎着裤子,诶转一圈发现出来了没有啊,再转一圈出来了没有啊。

好这个东西叫做cs这块大家能get到,来人给的老师可以,诶那行嘞,行嘞,水煮鱼可能有点误会,能否把电脑版网址发一下,收到消息,微信公众号里看哦,你找班主任要一下水主意,就是咱们所有的所有一切找班班啊。

班班都给你解决好,所以那个所有一切去找班班啊,小鱼鱼看这里啊,那这个O点notify oder,Notify,唤醒一个线程好,其实还有一个调用方法啊,其实还有一个地方方法,这个方法叫什么。

这个方法叫做O点OO点,Notify all,Otify,NO all的意思是什么,notify all的意思是,把等待队列里面所有的所有的线程全叫醒,Older notifo。

这个队列里面所有的线程全校性叫醒了之后,让让让他们老老实实去抢锁链,谁抢着算谁的,来这两个概念的区别大概就明白了,当然这里面呢我看刚才有同学问说,那个什么是公平锁,什么是非公平锁啊,什么是公平。

什么是非公平,听我听我说一句啊,三期王送contra hashmap是不是用的锁,C可能还是Mac,用的是cs啊,不是这个synchronized,还是听我说这个什么叫公平,什么叫非公平呢。

嗯以前有同学的,他的错误理解是什么,就是说到你了,然后下一步如果如果有两个线程,一定是你先我我在你又又是你,又是我又是你又是我又是你又是我,不一定的,不一定的,听我说所谓的公平锁的意思是说。

这是我们的队列,他在这里等待着这个队列,好这个队列,公平锁的意思是,当新来了一个县城,是直接去抢门上那把锁,还是进入队列等待,这个是公平的含义,那如果是公平锁,就是您新来的县城呀,不要去抢这把锁。

你直接进队列,我只要对烈士里边里边有人,你就得老老实实给我排队去,这叫公平,有人说上来就砸门是吧,谁抢到算谁的,那个叫非公平,听懂了吗,就是这个跟新来的县城是有关系的啊,新来的排队就是公平。

新来的不排队呢就是非公平,还有同学说,老师我总是要找到下一个线程去执行的,在这个队列里面的是有一系列的这个队列里面,我要优先唤醒谁,是有一系列的算法,这个算法被操作系统老大。

叫做那个线程调度器的一个东西来,由他来控制,因为这块儿再往下讲,我就我就只能给你讲操作系统的原理了,叫线程调度器,而线程调度器它本身自己又有好多种算法,像LINUX目前用的最多的叫CFS。

叫completely fair strategy,叫完全公平算法,所以这里面他叫醒哪一个,Order notify,叫醒哪一个,我跟你说的不一定的好吧,佳佳县城调度器怎么决定下一个拿到锁。

哎呦我这我这费半天劲给你讲这么半天,线程调度器自身需要用各种算法来做决定的,各种算法有优先级,有执行时间,然后呢采用了一种比较复杂的,叫目前用的最多的啊,所以好多种算法目前用的最多的就是CFS。

LINUX的底层调度原理,LINUX底层调度原理,因为今天也有听课的VIP的,在在听LINUX底层调度原理呢,我是,啊我是在这门课里讲的,就是这个程序员应该掌握的底层知识,操作系统的进程管理。

在这块讲的听懂了吗,所以你要是有VIP的,直接去听就行了,这里面我告诉你了,所谓的CFS是什么情况,这么跟你说,如果你想玩嗯,比较高级别的这种面试,这些是必须掌握的。

叫CFS叫completely fair strategy,叫完全公平,算法,完全公平并不是公平的,说每一个每一个每一个时间,每个时间都是一样的,那个叫做平均时间分片算法,那个算法是不公平的。

其实本质上是不公平的,LINUX所采用的就是综合考虑你的优先级,综合考虑你原来等待的时间,然后做了一个叫CFS的算法好吧,面试不问,大家不用纠结,LEONLEON是这样的,面试问不问这件事。

不是你说了算嗯,曹老师sorry,黄老师去阿里面试的时候,问的是LINUX内核的这个0X80的调用过程,0X80调用过程面扎瓦,所以不要认为人家不问,已经有至少有好几个同学遇到过这个问题了。

可能有可能你你你薪资问题,所以他们没问,你好吧,好不说了啊,我同事前端去阿里面试问的LINUX和算法,那就对了,我个人判断在未来的几年应该会发生,成员行业应该会发生两大转变。

第一个呢一点都不懂AI的哥们儿,你呢等待被被再一次被时代落下,第二个是你不以算法为核心的,全是学应用的,就是原来那种旧培训应用就教你工具怎么用,怎么去建项目,死死的CRUD这个基本会被落下。

今年这个趋势已经很明显了,像前半年的时候,上半年的时候大厂的面试还不怎么,除了字节之外,还不怎么涉及到特别复杂的算法,到下半年开始,各种面试算法特别特别多,所有的面试官其实最后都会意识到一个问题。

程序员最核心的东西就是叫算法,就是所有东西都是算法逻辑能力吗,你算法如果真能考过关了,我跟你说,也就相当于你的程序员一定是合格的,你懂吗,这也是唯一一个你走不了捷径的东西,LEO灭了三次支付宝年底再战。

继续,不会AI,只会API,那就完蛋了,左神的算法是不是可以涵盖大部分了,左神算法可牛逼到什么程度。

这哥们是嗯训练营第三期完了,然后他大概拿了offer,阿里腾讯,百度美团,滴滴快手虾皮,华为招银前进,大华投入嗯,这个一点不夸张啊哈哈。

他是面试专业户哈,有可能,啥时候来自算法公开课,左老师每周都有算法的公开课,你可能没注意,另外我们管理P6没问我算法过,就是spring源码和一些技术,你再你再念,你试试看,阿里呢它有不同的bu。

不同的业务线,不同业务线面临的情况不太一样,有的呢我可能就需要你过来做应用,所以它有可能就不考你算法啊,阿里确实考算法,考的不算多的,算法最多的是字节,腾讯华为拼多多这些美团快手,这些是最多的啊。

没见过老做老师的公开课,华子不是每个人都能成为神,所以不用努力了,你说的很对,华子可以成为半神吗,你不能成为超人,但是也可以成为蝙蝠侠呀,华子我不是这个意思,我说你是你就是开个玩笑,开个玩笑啊。

来来来来来,大专学历是不是要被淘汰了,你你你我弟问的那个马云是大专吧,好像是是不是忘了嗯,好了好了,我们回到那什么吧,我们回到回到回到回到我们的技术层面,技术层面看这里啊,嗯大专,对啊,大专好多的啊。

谈不上淘汰,其实那个学历就代表着,你年轻的时候有没有努力过,也许你年轻的时候那时候没努力,后来开窍了,进行了一系列的努力,也并不代表你的水平就差哪去,所以别这样啊,如果一个人真的一个标签。

就能把他给淘淘汰掉的话,那这人也太简单了吧,这个世界是不是也太简单了,非零即白啊,非非非黑即白,非零即一,成员的眼里的世界就是这样子的吗,提高一下情商,用灵活一点的角度看世界好吗,来看这里啊。

跟你们聊聊天,真费劲啊,太轴了,好大家,如果你明白了这个weight是什么意思了,明白了notify是什么意思,明白了NOTIFO是什么意思了,但其实你发现没有,像这一类的同步机制。

就是weight notify呀,是必须要持有锁才可以,比方说我如果我作为一个另外一个线程啊,我作为县城,我想叫醒你的话,也许你得摸这个锁,把我先持有锁才能去叫醒这个锁上面,等待这些队列的所有的人。

这是第一个,就这个锁呢是这个同步机制是有些问题的啊,这这是第一个问题,第二个呢是这哥们儿只有非公平的,没有公平的,只有非公平,就是你来了之后直接抢,谁抢到,就算谁的,第三个呢是这哥们呢。

他的队列里面不能精确地叫醒,不能精确叫醒,举个最简单的例子,我们刚才所说的这个呃,有有有有一部分人往里头扑哧扑哧,往里往里往里往里搁东西啊,有另外一部分人往里头消费啊,往外抽东西。

那好那这些个对于这个锁的访问的过程呢,这些个生产者会进入到这个队列,而这些消费者也会进入到这个队列,生产者什么时候进入队列啊,满了的时候,消费者什么时候进入队列呀,空了的时候。

所以当我们用这个NOTIFO的时候,我本来只想叫醒消费者的,我不想叫醒生产者,但是没有办法的,没有办法,你必须得叫醒所有的,当你使用order notify,如果叫醒的,你本来本来想叫醒的是一个生产者。

不想叫醒的是消费者,结果你不小心叫醒了消费者怎么办,你这个消费者必须得再负责叫下一个,所以这程序写起来是相对麻烦的,这是它所带来的问题啊,我再说一遍,看大家是不是能听得懂。

因为这里面涉及到方法论的一些东西啊,就是你像这种队列,就是第一个呢这个队列呀,它是你,你你不可以指明你,到底我想叫醒哪一个或者是哪一类,这些都不行,叫醒哪一个也不可以,叫醒哪一类也不可以,或者双向队列。

两个队列,两个队列,如果有三种类型的人呢是吧,你不能不能只能说我灵活的可以指定多个队列,听懂了吧,这是解决问题的方案,还有一个呢它是公平的,他永远都是非公平的啊,不可能是公平的,Ok。

所以呢就诞生了那个其他的这些个玩法,这个玩法不知道大家有没有见过啊,这玩法不知道大家有没有见过这玩法呢,叫叫叫lock support,这东西是不需要你不需要持有锁的,它写起来要简单的多。

比方说我让我想到一个县城,当前线程阻塞,我怎么做呢,其实非常的简单,就干这件事就行了,叫lock park,park是停车的意思,停车的意思是暂停到这,你给我暂停哪个线程,程程暂停不就阻塞了吗。

线程暂停是不是就阻塞了,阻塞了到这是阻塞了,然后我怎么想叫醒他呢,Log support on pack,把这个现成的名字传进去就可以了,这就简单简单好多了。

因为这里没有涉及到任何的synchronized,上锁这个概念,你直接拿来用就可以,哎哥们,我现在正在park的park,我就暂停了,我一看里边有人,我就直接park了,谁想叫醒我,把我名字传进来。

提这个事儿呢,就相当于你自己写了个调度算法,你想叫醒哪个,叫醒哪个,而刚才的notify是不能叫醒指定线程的,只能说调度算法来帮你决定调点加强哪个,有同学说以后我全用这个吧,不一定的。

你自己写的调度算法,真的一定要牛过操作系统的调度算法吗,don't think so是吧,这个T是什么参数,这个T不就是现成的变量,就是线程,就那个人,停车释放CPU吗。

park这块它内部的过程是有一个升级的过程,如果没记错的话,他应该是一个升级的过程,刚开始是用那个自旋哎,那个轮轮到我继续往下了吗,转了几圈之后发现轮不到他就进入队列了,所以它有一个优化过程。

这个要看具体实现的啊,不一定是有不一定会进对联,也不一定不进,就看他的视线是怎么写的,自适应自旋,所以内部实现未必使用了自适应自旋,好这块大家能get到吗,能get到,老师扣个一来我感觉大家伙的感觉。

大家伙的基础看着有的人看上去很牛叉,但真正一聊发现,嗯比较稀松,面试这件事是一定要能说得出来啊,雷克雅维克,我就是个菜鸡,你不用看上去,那怎么着怎么办,你作为一个菜鸡,那只能咬一口了。

队列是object monitor,ENTRALIST队列,object monitor有三个队列,entry list是马上要执行的线程,weight set是放在队列里等待着被调度的。

这个不一样的啊,好嘞好嘞,那嗯这个是一种玩法,咱们说还有一种呢是我我就我想叫醒一类人,那想叫醒一类人的话,这个该怎么办呢,这个是另外的一种锁,这个锁那叫reentrant lock。

Reentrant lock,好,这把锁的这把锁比较好玩,嗯他也可以做,公平的也可以做,比方说被打断的锁定过程也可以做呃。

系列 5:P26:26、ReentrantLock - 马士兵学堂 - BV1E34y1w773

这样吧,这样讲起来真的就没完了,几点了,九点,降到哪里算哪里好吧,这个reaction log部分场合也可以替代,Synchronized,它是替代什么,它可以做公平锁,他有这么几个特点跟大家说一下。

可以是公平锁,可以是被打断的,可以可被打断的,上锁过程,像原来那个synchronized的,你是打断不了他的,你不可能用interrupt把它给打断,这个是可以被打断的,还有一个呢是,锁上面的队列。

可以指定,任意数量可以指定任意数量嗯,怎么跟你说呢,听我说啊,比如说啊我给你先消化原理,先不先不看这个代码怎么写,代码写起来比较简单,如果是这个这把锁,Ranrolock,如果net是这把锁的话。

L l range lock,那么这个时候呢,你可以指定它在上面有多少个队列,每一个队列呢被我们称之为一个condition,以前很多人讲这个condition的时候,老师在这种条件下怎么样。

在这种条件下怎么样,不要把condition理解为条件,把condition理解为队列,凡是new一个肯定是出来的时候,你就认为他有一个队列就可以了。

reaction lock有各种各样的condition,也就代表着有各种各样的不同的列,每一个condition你自己去new听懂了吗,你可以new好多个的,可以来一个生产者的队列。

可以来一个消费者的队列,可以来一个监管者的队列,计费计计数器的队列对吧,计数的人的队列都可以,那么当你要叫醒某一个的时候,非常简单,你就指定说我要叫醒这个队列的人,我要叫醒这个队列的人。

或者要叫醒这个队列的人,这是他的原理,哎这会儿能get到的,到时候扣个一,公平锁FIFO,你要这么聊,公平锁就太简单了,公平锁我刚才解释半天,结果发现你们理解的还是不对,你要让老师要怎么样。

才能够拎着你耳朵给你灌进去吗,公平锁就进入队列,但是这个队列下一步是不是FIFO,那是简单的调度算法,是有可能被操作系统的调度算法所决定,拎出来的,可能是这个,也可能是这个,也可能是这个。

当然他可以提前排好序,那个就叫FF了啊,但是并不是时间点上的FFO,EQS就完事了,EQS是自己写的调度调度算法了,AQS是JVM自己写的调度算法好了,这是reaction lock。

它本身的一个小含义,那他应该怎么写呢,应该怎么写这件事呢,给大家看代码片段吧,就就就就不去不去解释每个代码的含义了,你看这里啊,代码片段,作为我来说,我有一个reaction lock,与此同时。

我可以new出两个condition来,一个condition producer生产者,一个condition consumer,消费者,new new出来之后呢,put put线程啊。

put方法一般都是生产者用的,往里头put,所以生产者只要是我满了,list size等于max while循环,只要它满了,那你就await就可以了,producer await这种。

这就等同于我们前面所讲的什么东西呢,我前面所讲的O点weight,o weight是什么意思来着,还记得吧,这把锁上的队列,当前线程进入这把锁的队列,Producer weight。

当前线程进入这把锁的生产者队列,我这原装满了之后呢,我就wait了,我就开始往里加,加完了之后呢,Signal all,我加满了,我要叫叫醒消费者,哥们你赶紧去消费啊,signal去消费,消费消费。

Come on,赶紧去消费,好叫醒叫醒消费者,那消费者怎么做呢,消费者一旦空了,进入消费者等待队列,叫醒生产者,赶紧二话不说,快点给我去生产,因为我已经空了好了,同学们。

这个小程序就是解释了一下lock,Reaction,lock的含义,如果你要synchronized写怎么写啊,SYCHRONIZED写起来就得是,我我lock当前对象。

所以this weight这个weight就进入他,就他就没有分的那么细,他就只有一个队列啊,你这么理解就可以了,好嘞,这会儿能get到的老扣一吧,就是ANCHLOCK啊,这logo还有其他其他用法。

但是最主要的最主要的其实就在这,这就是信号量,Major major,你那个该该哪凉快去哪,待会好吧,这跟信号量没有半毛钱关系,这个叫信号量,叫SAMF嗯,锁的自从自从并发诞生以来。

各种锁的概念层出不穷,没有有的人呢把这个叫A所有的人呢,把这个叫B所有的人叫C锁,每个人都想证明自己,我说的这个最具权威性,知道概念是什么意思就OK了好吗,不要去追求细节。

非得说这个概念我就对那个概念我就对,这东西有人叫他便便嗯,有人叫他翔,你非得说叫翔就是对,叫便便就不对嘛,别这样别这样,OK自选所有人叫他无所,你说多讨厌对吧,然后马上就开始有后面有杠精就开始说了。

无锁到底是不是一把锁,就这么无聊,别这样啊,理解理解这东西,然后找一个约定俗成的叫法就行了,你又不是你又不是那个那个那个啊,索命名委员会的是吧,三七王松工作中是不是很少用啊,非大厂。

你要写CROD基本用不着写中间件必须得用,讲道题吧,讲道题吧,我不讲题的话。

很多时候你也理解不了这个锁的含义,讲题之前把这个概念再给大家介绍介绍。

分布式锁是不是更复杂,分布式环境没法用,分布式环境怎么没法用,就是你学死了,你会觉得分布式环境没法用,分布式环境的本质也是说到某一个地方去上锁,上完锁之后把它变成序列化,它的本质也是一样的,没有区别。

理解了锁的本质跟它是分布式还是单机,没有直接的区别,只不过有的人如果让你自己写,你就琢磨琢磨,你就琢磨一件事,如果让你自己写,自己写一把分布式锁,自己写,你会怎么做,找一台机器在上面记录一个数字。

所有的机器都访问了一台机器,把并发搞成一个单点序列搞定,就你不要用中间件,你自己写不就这样吗,所以最早开始的分布式锁就是数据库级别的,数据库里加一条记录不就不就搞定了,每次我要干的时候查这条记录在不在。

搞定了之后把这条记录给删了搞定,所以这东西本质是一样的啊,当然分封锁它的实现上的理论上是这样的,它实际上会稍微复杂一些,因为它要牵扯到各种的可用性,安全性呃,扩展性,把这些都考虑到包,包括性能。

所以呢就诞生了各种各样的方法啊,比如说用数据库的悲观锁,用数据库的乐观锁是吧,数据库相关的,用REDIS的各种锁三或者REDITION的红锁RELOCK,zookeeper的这叫强一致的锁。

这个锁呢叫做弱一致性,这个锁强一强一致性的锁,强调CP的,但是他效率他强一致,一致性高了,并发量肯定低,比JK更好用一些的ETCD是吧,哎也可以,甚至你可以自己写,阿里有阿里有道题。

基本上就是分布式事务吧,那个不能叫分布式锁,相关的,就是总而言之呢,学东西呢从底到向上慢慢的学好吧,先把最基本的概念理清楚了,再去聊这个分布式的,给分布式分布式事务呢大概讲的内容,我们大概讲了六节课。

六节六节整整的大课,所以东西还是比较多的,先把单机版的你先理解透了啊,java博大精深,不不不,这个跟java关系并不大,王松你要这么理解,反而就那个什么了,因为你想啊就锁这个概念本身啊。

他跟语言的关系都不大,你能听懂吗,就是他跟语言的关系都不大,就是其实类似于这样的东西,在C语言里面也有实现,有类库帮他实现了,在其他语言里面也有类库的实现,也有相应的实现,只不过我们在java语言。

你比较熟这个语法而已,从原理上来讲,这东西跟语言关系并不大。

学多了就可以穿起来,也容易理解和记忆。

系列 5:P27:27、Latch - 马士兵学堂 - BV1E34y1w773

那我们再跟大家聊一个常用的也是比较简单的。

就是这个latch哎,这有点乱码啊,乱码先不去管它了,就是这个LCH,这个LCH叫什么东西呢,叫countdown latch,Countdown latch,常常见的最常用的就是它叫CALLCH。

LCH是什么意思,latch latch叫门栓,就是我在这儿在在在你下面啊,一堆一堆人来了,想打开这个门,想继续啊,想打开门进去冲进去要干啥好,我上面有一个门栓,这个门栓门栓是用来干嘛的呢。

这个门栓上的你可以理解为是一个计数器,这个计数器呢从上往下慢慢数,计数器的初始值是100来一个人给他count down一下,Countdown,count down一下,100-99减一。

再来一线城又counter一下就减二,什么时候减到零了,这个门就开了,这是大概它的含义,理解这个东西呢,我给大家举一个面试题吧。

这面试题呢我原来在也讲过,咱们快速的过啊。

因为这里面实际上是把各种锁呀,各种的这个新的新的新的同步器啊。

你都可以练到,这面试题是这样的啊。

这道题,这道题是线程交替输出的问题。

我们这是阿里。

就是阿里呢他们有时候不考算法。

但是他会考考你县城,县城是比较好的,两个线程啊,一个输出字母,一个数字交替输出。

就是你输出一下,我输出一下,要保证这个东西一定是交替的。

如果正常的情况不做同步的话,就两个线程随意的啊。

我这边输出111~26,另外一输出A到Z,那中间一定是乱的,一定是乱的,而且现在我的要求是,第一个线程输出ABCDE,第二线程12345,必须得是交替的,A1B2C3D4啊,E5。

就是这样这样交替执行的好,这个就是两个线程交替执行的含义,这是他一道面试题嗯,这道题怎么着给他给他点思考时间,简单的把我刚才讲的这些东西,你琢磨琢磨怎么用,好不好。

一点点思考时间,有个三四十秒试试。

wait notify可以解决吧,我跟你说了嘛,这东西实现的功能是用wait notify,Lock,Condition,Lock support,它实现的功能是一样的,实现的功能是一样的。

都可以解决,你你你你你肯定得找那个最优解吗。

用起来最舒服的那个是不是。

compleable future的combine可以吗。

我觉得应该是不太可以的,不信你写写。

Then combine,Then combine。

then combine也不行,因为你理解错了三生石。

你理解错了,你好好琢磨琢磨哪里理解错了。

then combine是新的任务,大哥人家都说的是两个县城。

您老人家那个可说不定那得是52个县城了。

说不定就是52个县城或者县城池里面的,若干个三生石,三生石。

你想的是不对滴,lock support park和on park对你微笑啊。

微笑就想到了微笑。

就是这么个水平高,lock support park和on park。

只有输入了才输出。

你要手工控制啊,人家要求交替输出,你的意思是我手工来。

我敲一下到你了,你是在搞笑吗。

这道题大概有一百一百来种解法,100来种。

牛逼了老哥,你咋就又牛逼了,你为什么老说我牛逼了,我姓马,县城互相传输。

合着我讲半天来,你还是没搞明白我在讲啥。

这个叫现成的同步同步。

叫synchronization,MR公开课吗,Yes,公开课使用pk。

唐湘平,先把单词给拼对了。

pack打包,是因为可以指定唤醒哪个锁吗。

换哪个县城,哎呦喂。

谁让你唤醒锁了。

channel嗯,你的那个这个呃。

小土豆小伙应该是写go语言的啊。

你写啥语言,老师也能给你讲语言。

在老师这就是把不同的刀的区别。

两个condition应该可以,good可以啊,没问题,很对啊,你们你们说的都非常的对。

这道题啊,最早是一道填空题,你知道吗,特别好玩。

最早是一道填空题,填空题呢他最早的最早这道题是什么样子。

我跟你说,这道题最早是一道填空题,填空题呢就是你呢应该你持有这把锁的时候。

是在这里要填notify呀,还是要填weight,填wait啊。

还是要填notify啊等等,我们先说我先说先说比较比较那什么的方式吧。

嗯突然有种降维打击的感觉。

有种被降维打击的感觉,为什么嗯你发生了什么。

你为什么被降维打击,女朋友叫你去,你女朋友叫降维,是你女朋友。

为什么不叫蒋大为,好看这里啊,我们先来聊这种这种方法。

我们来看这个lost park和on park该怎么做啊。

我们两个线程啊,这两个线程1234567ABCDEFG。

第一个线程开始执行的时候是怎么做呢,就是你上来有一个线程。

先让他park自己二话不说,先park懂吗,先让自己暂停。

先让自己暂停,能保证一件什么事,一定是呃,这哥们儿那个等着被唤唤醒了之后,你才可以继续执行吗,而另外一个另外一个线程怎么执行的,另外一个线程就先打印吗,打印个一,他打印完一之后,打印完这个一了。

然后再去unpack t2。

所以这个方法其实是最简单的,只不过原来呢很多人考试的时候。

他不了解这个方法,所以呢他就他就他就写了个特别复杂的,With notify。

体会到了吗,就是你让第二个线程上来,二话不说,先park,等我的第一个线程打印完成之后再调用on park。

而且它能保证你放心。

一定是先打印一,而不是先打印A。

阿卡陈汉典老师教英语吗。

想跟老师学英语,可以教老师,原来在新东方教过英语好,在这里pro one打印完之后在on park第二,然后on pk完了之后,注意on pk完了之后,他自己要立马去干嘛,要立马自己去park。

要让自己去赶紧赶紧赶紧park住这块儿能理解吗,让自己赶紧趴个主嗯,赶紧派个住之后呢,然后另外一个线程打开,他继续往下执行了吗,因为他被叫醒了,继续执行了,打印A打完edge。

打完A之后再叫醒T1。

就这样交替的一步一步地执行,自己在park和这个过程大家能看懂吗,抽烟上来一个线程,先去park,然后再打印一,叫醒刚才被park的线程,自己再去park这边打印完A。

接下来把刚才帕克的都叫醒了。

自己在帕克互相之间这么来回调,嗯来这个过程能get到的,老师扣一,所以这个写法是这样的。

但其实这个写法有一点点小小的bug在里面,比较隐蔽。

今天懒懒懒懒懒得讲了,就这样吧,大概能理解什么意思就OK。

好看这里啊大家写法就是这样的啊,两个线程T1T2T一,第一个线程是打印数字的,然后打印完数字之后呢,挨着盘的从数组里面把数字拿出来打印,打印一个叫醒T2,叫醒T2自己睡去,自己阻塞。

然后T2怎么做呢,T2应该是上来自己先park,先自己park,这样保证一定是T1先执行K。

这写法大概就这样的啊,来这块可以继续吗,没问题吧,两个同时异步跑on帕克的时候,对方不一定帕克怎么办,青色渡鸟,青色渡鸟水平不错啊,这么隐蔽的问题你都能找得出来。

青色渡鸟小伙伴们,新政体体体会一下青色度鸟的问题,然后自己尝试解答一下,两个同时异步跑on park的时候,对方还没帕克的时候怎么办,咳咳对方还没拉呢,你就让他擦屁股怎么办,上来拿纸先擦。

这肯定不合适啊,这块能理解吗,就这哥们还没park呢,你这时候有可能已经掉了on park了,这哥们已经掉了on park了,这个很正常啊,你比方说他就要选T2了,然后这哥们暂停了吗,在这暂停了。

然后T2线程的是打印完之后马上去调on帕克,T1,您这您这会儿还没还没帕克呢,能敏锐的发现这个问题的小伙。

青色渡鸟,你不应该叫青色,你可以写成红色了。

Sleep,我靠我就我就烦,有人说这sleep的,谁要是在现场同步里面玩sleep,你赶紧抽自己的两个,挤好几个大嘴巴子咳。

你知道你要睡眠多长时间吗,你说我睡十秒够了,万一不够呢,你到底要睡多少,谁要是在县城同步里面玩sleep,直接抽自己嘴巴子啊,好听,我说这件事非常的简单。

因为作为咱们正常的上锁解锁一定是lock lock,然后再unlock,但是这个park和on park是可以反过来调用的,你可以调用UNPARK在先,然后他在park。

那么这时候产生的效果会是什么样的呢,产生的效果是这边先调用了on park,然后你再调用park的时候,发现有哥们已经调用了on park,我就park不住,就直接去执行了,这块儿大家能get到吗。

你不要这样地看着我,加什么判断,还有这操作,是的,这就是帕克和on帕克的细节。

嗯好啦,我们就到这吧,好这是最简单的解决方案啊,多次park会计数吗,会的会计数的,on park t2T二,可能空指针。

来你告诉我,你告诉我。

我先把它弄完了,然后再调用的start,你告诉我怎么控制,为啥呢,指令重排了吗,跟指令重排有什么关系,还有孔子真脑子里咋想的,不好意思,看错了,看错就要被怼,在老师的课里,看错就要被怼。

当然你也可以怼我,你要水平够了,我欢迎你怼我,好下一个你看小土豆说下一个好,就听小土豆的,下一个挑几个比较好玩的解法啊,现在09:30讲几个得了,因为这题啊大概100多种解法。

真讲完也没什么意思,有一些就是就是就是属于特别无聊的。

脱了裤子放屁的那种就算了,自旋锁我就不讲了啊。

这手工实现自旋锁就不讲了,好咱们说这个synchronized the weight和notify。

就是最原始的,这也是最原始的解法,Sychronized way,notify应该怎么做。

很简单嘛,就是我首先让线程一启动持有这把锁,注意一定是synchronized这把锁,持有这把锁持有并且打印。

打印完之后就是第一个线程吃掉,并且打印打印了个一嘛。

打印了一,然后打印完之后通知另外一个县城。

哥们儿,你该醒了,或者通知这个锁上的队列。

队列等待的线程该醒了,然后自己一定要去wait,要去释放这把锁,如果你不释放这把锁的话,另外一哥们儿是持有不了,是拿不到这把锁的,所以一定要释放掉它。

Wait,然后这哥们呢第一个线程打印完。

通知完,自己去wait了,第二个线程抢到那把锁。

持有并打印,Notify,自己去wait。

就这么一步一步一步一步能看懂吗。

因为锁本身就是个奇数,就很像可重入锁,反过来应该也是可以用的。

辣椒我懒得怼你了,就当你说的对。

我看所本身不是技术,所本身的实现是一个lock record,放在县城站里面。

好了好了,咱们这个就扯的太太太深了。

来看这里,可以先wait和notify对,问题就在于你不可以先notify再去wait,On park,那个有可能没有帕克是怎么解决的,那是你那这个很简单,就是出bug了,你自己重新写。

那最后是不是要finally。

你在说啥,如果描述不清楚代码问题的。

就直接拿代码描述,不要拿嘴描述。

嗯拿嘴描述出一个代码问题,一个技术问题是很需要技术的。

你要是有这个能力的话,你的技术可以很弱,只要面试比较强就行好这个写法也比较简单。

大体的算法应该大家都知道,我们来看看这件事怎么写。

Synchronized we notify,就是无非就这么玩吗,仔细看,这是第一个线程呃,打印数字,打印完之后叫醒另外的线程自己去wait。

那第二个线程呢就是打印数字,叫醒另外的现场,自己去wait,两个县城都一样搞定嗯,这块不知道大家听清楚没有,然后这里面有几个,为什么说它原来叫填空题,因为他原来把这个地给空掉,让你填空。

这里面要填什么呀,是填到TIFY呀,还是弄一个O啊,还是wait啊,OK这里面最容易犯的问题就在于,这两句话能不能换位置。

再说一遍,这两句话能不能够换位置,思考一下好吗,那个,我们我们先说第一个问题啊,刚才那小伙被怼的那小伙叫啥来着,忘了欧点weight o点,Notify,这哥俩能不能换位置,琢磨一下能换吗。

这肯定不能换啊,大哥wait是几个意思啊,wait是几个意思,我想我想问你,wait的意思是,我进入等待队列,等着别人唤醒我,我才能继续往下执行,您老人家先把自己给wait了,先把自己给干死。

然后再去想着去干别人,先把自己砍死,再把敌人砍死,哈哈你跟你跟你跟你跟李冰冰有一拼啊,铁锅炖自己对好,这块这块能知道了是吧。

这块肯定是不行的,这块肯定是不行的,这是这是这是第一个问题啊,第二个容易出错的点在哪里呢,在这就是当循环结束的时候,当循环结束的时候。

看仔细看,当循环结束的时候,为什么还要在这里加一个notify,跑一下。

来虽然它是1A2B3C4D五,什么什么来输出的,看到了吗,但是呢他不结束,你发现没有不结束,琢磨琢磨,为什么我们琢磨一下嘛,按照这张图来说。

我叫醒你去自己喂它,我叫醒你自己喂它。

叫醒你自己喂它,总有一个线程也可能是A也可能是B叫醒了。

最后对方最后一次,然后自己去wait。

没有人再也没有人叫醒他了,因为这哥们已经结束了。

死锁之弦呀,哎呀让我说你啥,这跟死锁有半毛钱关系吗,他就是有一个县城,最后在那里,Wait。

没人叫醒了,所以你要想让县城正常结束的话。

在你循环结束之后,一定要加一个O点,notify或者all,查一下正常结束,顺利输出,正常结束了,同学们这块没问题的,老师扣个一,大家都明白,Synchronized with notify。

怎么玩了是吧,有问题你直接提啊,为什么wait notify都是O小深红,你是半截单进来的吗,合着我讲半天白讲了,这是这个学到了啊,之前面试手写没考虑过,这个也过了,利用对算你运气好。

你说这个程序相对来说比较简单的嗯。

那个我们说这里面还有一个隐含的小bug小问题。

假如我要求你数字必须先输出,或者字母必须先输出。

系列 5:P28:28、从独占走向部分占有,Semaphore实现线程的N个共占 - 马士兵学堂 - BV1E34y1w773

这个小程序呢基本上就没什么问题了,但是呢这里面有个哪个线程先启动的问题,它有可能是先执行的数字,也有可能先执行的字母,你怎么控制这两个线程的先后顺序,启动的先后顺序,你怎么控制。

怎么控制这两个线程的先后顺序,启动的前后顺序怎么,来个十天的,我刚才给你看这个聊天记录了吗,这个聊天记录的第一次,我给他做规划的时候是10月31号,提前wait,提前wait可以,这个是是一种方式啊。

这个an an o a NO o d a NO可以啊,提前wait就是有一个呢先wait一下,然后notify再继续可以,但写起来比较恶心,比较麻烦,写个变量做判断,写个变量做判断,小强啊。

哎不是小强啊,Skating,写个写个变量做判断,你在你在搞啥,你那个变量要不要加同步,你怎么着,你再来一同步,知道吧,同步两个对象的时候就容易产生死锁了,好这里可以用到什么呢。

可以用到CALLCHLCH,还记得那个latch是什么含义来着吗,的含义是有一个门栓,这一道门门栓上有个计数器是吧,哎我这个计数器呢给他写了个一,我让第一个线程上来之后。

先await wait的含义是这个门关死,门栓的上面写了个一,一变成零程序继续往下执行,听懂了吗,这个也是可以做的,Ok let await,第一个线程现在现在上来,先await。

那什么时候这个门栓继续往下执行呢,所以第一个线程执行到这里就先暂停了,他不会输出的好,第二个线程是这样做的,当他输出了数字之后,让这个门栓充当输出完数字才让他count down,那么你仔细琢磨一下。

我,我肯定是第二个线程先输出,输出完了之后,第一个线程才会继续往下运行,才会输出,五天A来这块能get到的倒可以,所以门栓的含义就大多数是用在这种语境上,就是到某一个点上,我必须暂停,嗯说到这儿呢。

我们就说一点那什么吧,嗯比如阿里有一道面试题,有一个很大的任务,AA任务分解成为A1A2A三,A 4a5 a 6a n,那么形象化的理解你可以这么理解,我要吃火锅好,我这是我的总任务。

我要派一个县城去买肉买菜买油买锅买柴火,那么这个时候我怎么去等待这些现成的结束,然后我烧好火锅之后跟着等着,等完了之后才能继续,怎么等待这些线程的结束呢,有一种方式还记得吗,叫join,Join。

Join,这种方式也可以,也没问题,但是你得挨着盘子去join,你不如在这里设一个门栓,在这里设拴住,这里记录这个数字,五,这个线程结束了,正常结束了,calm down变成四,这个线程结束了,变成三。

变成二,变成一,变成零的时候,说明所有线程正常结束,来火锅开动,Calm down,calm down lash经常被用作等待线程结束,你看波澜不惊多牛叉,我给他讲A他永远都是找我要币啊。

这些例子太平常了,有没有企业级的线程池运用累,每个人的水平不一样,波澜不惊的水平应该相对高,我希望相对高的同学们照顾一下,咱们零基础的这堂课,我第一次上来,我就先讲了。

今天我们主要讲应用级别比较简单的东西有,但不是这堂课讲VIP课里全有,线程池,我需要你了解基本的同步机制,我需要你了解同步队列,需要你了解手工创建,需要你了解各种各样不同类型的线程池。

我们才能聊企业级到底怎么用,洗衣机的用法,用的最多的scheduled fork join,以及非常普通的手工定义线程池,我跟你说啊,也跟大家说一下,就是很多时候是这样子的。

在一个多线程这个这个东西用的最多的地方,其实还不是企业级,其实还不是企业级,是什么呢,是那个那个那个那个就是面试啊,我告诉你前天就被灭了,这道题最后给了21KCML啊,张保伦真的是这样的吗,没关系啊。

咱们我们整体的班型呢,现在又是从零基础开始的呃,你像整体版型现在做的越来越越那什么了啊,你像入门性的基必备知识从哪开始讲啊,硬件的基础,windows命令行的基础虚拟机怎么安装,二进制是什么东西。

另一个常用命令怎么做,JAVS的基础是吧,嗯基础的核心面向对象集合等等嗯,MYSQL的基本的语法,前端的后端的设计的,然后那个呃基本的数据结构的,基本的算法的贪心和暴力递归呢,整理之中包括动态规划呃。

源码的解读的,然后工具的使用啊,团队的协作的项目的保障呢。

还有呢过相关的项目,这个大概就是一个零基础的课程了,所以你没有关系啊,就算你零基础跟着老师踏踏实实走,涨个薪水也跟玩似了啊,用对方法仨月足够看这里啊,这个就是门栓所常用的一些地方,好吧,好嘞嗯。

这是这道题呢,就是原来特别正统的解法,当然还有其他解法啊,还有一些其他的解法,这个图能发下吗,看下课程呃,这个图是目前整理了入门级别的了,我们进阶级的正在整理的过程中,就是原来我就是这样的啊。

就是原来的老图呢是这样的一张图,从P5开始,P5你应该掌握哪些,P6应该掌握哪些,他不是这张图不好看吗,所以我们就换了一种展现形式,这也是课程的升级之一吧,P7应该掌握哪些,P8应该掌握哪些嗯。

对整体各种细节的东西进行了分析,但是这个里面的组织的不是特别好,就是没有侧重点,然后详细的点呢并没有专门列出来,所以我们专门又组织了另外一种展现形式,听懂了吧,呃稍等两天,直接就在网页上了。

你就可以看了,好,那怎么成为VIP,你手里加小姐姐了吗,去报名,我再跟大家说一下,做好规划这件事超级重要,现在11月份,明年的金三银四,大概还有半年,半年时间,是足以让你达到P6P7的技术要求的。

听懂了吗,技术要求一定没问题,但是时间再短,你就只能走捷径,走捷径的成功率就没那么高了,像这种的成功率超级高,呃,我们课程的我要我要帮他做完规划啊,大概你说大二大三的学生,如果你是二本以上。

差不多基本上90%,我送你进大厂了,大二大三,因为你有一年的时间跟我们练,那太充足了,但是到大四呢,你基本上就只剩半年半年时间给我们练的话,这个概率就要低一些,一到3年概率会更低,这个时候玩7+1加一。

这个时候玩6+1,这个时候必须得玩6+2了,这个就要难好多,还有因为加项目必须得加项目对项目的理解,而你原来项目不给力,做背调,你还就完蛋了,好三到5年这块要玩的东西就比较多,八到10+2了。

因为这个东西除了项目,各种软性的东西就全来了,这个时候你必须得是P7了,像这种的基本上就是P6嘛,相对简单的多,像这种都是P5哇,太简单了,对我来说太轻松了,我强烈建议你这个时候你如果是这批人。

抓紧时间过来,好,以工作加大专呢,大专生看个简历吧,我们自己的一个简历简历,自己学生的简历啊,呃这小伙原来是做游戏后端的,他游戏后端的主城呢,大概的月薪应该是3万多到4万左右,是到到头了。

就嗯这哥们跳完互联网之后呢,他原来是拿3万5,然后跳互联网之后拿60万到70万,年薪大概5万5万到5万多,5万到5万5,我们课程呢我一会给你介绍一下,你就知道啊,就课程里面的这些东西,他就写了五条。

五条足以涵盖5年以下开发管理经验,负责项目日活300万,注册人数1。3亿,夸张了,不过没有关系,无所谓,游戏嘛对于构建高吞吐,低延迟分布式架构有分有分布经验,那么这块主要是什么内容呢,这块主要是指的。

我们的那个整体课程架构里面的,P7级别到P8级别的课,打开来瞅一简单的,就是这块呢主要就是指的是这部分的课了,分布式全体的理论,加上呢整个分布式的落地实践嗯,比如这个分布式id的中心怎么搭是吧。

然后配置中心锁集群事务集群,各种各样的集群,网关E的服务器,搜索集群,查查dB的这种分布式调度是吧,tan群MYSQL的集群等等,就是他指的是这部分了,好吧嗯,简单分的话,这部分30万到70万。

这部分是30万到70万的项目啊,这部分是30万到70万的项目,怎么做推荐系统,做画像怎么做那个spring cloud的地呃,怎么做蓝绿发布,灰度发布啊,怎么做ab测算等等,怎么做。

这个分分分分分分布事务的解决方案,到底应该怎么做,t cc的方案啊,LCN的方案,然后那个呃theta的各种解决方案,最大努力通知方案,A方案,事务消息方案等等都可以,就是加成项目吧。

就是基础的理论知识啊,加上项目,我今天给大家讲的,大概就是整个高层体系中的一门课吧,一门课里面的一小部分都按照高并发,这是第一版的第一版内容,这是第一版内容,因为他第一版的每个有两到三个小时的课。

特别长,所以我第二版就更新了一下,把那个细节的内容,把好多东西加上了,把好东西讲细了嗯,这两个拿下30万到70万,然后再想往上高,就是这个MCA架构师,从架构师的理论一直到落地,一会儿你要有兴趣。

我就给你详细解释解释啊,全国大概课程最多的课,课程最深的课,课程最长的课,又长又粗又深,如果找到比我们更长的更深的,这课可以免费送,你没有能做到这一点的,主要原因是因为舍得请人。

我们有20多位一线大厂的老师讲一门课,这也是很多机构都做不到的,好吧嗯,OK不说了,就这哥们大概是大专吗,27岁转过来运维60万到70万,融360,好嘞那个技术技术技术技术的聊两句,因为我还没聊完啊。

感觉呃,这因为这种这种的各种各样好玩的,解决方案也有特别多,像这种叫pp stream这种线程之间直接弄一根管道,互相通信的也有,用blocking cube也可以实现啊。

用atomic energy也可以实现,也没问题,用那个那个那个呃EXCHANGER就实际上实现不了,用SAMF得用两个SAMFA,用一个也实现不了嗯,说到线程池。

线程池是需要聊到那个那个刚才说到线程池,线程池是需要聊到这种消息队列的,任务队列,任务队列,那任务队列呢我给你讲个比较好玩的,就是你可以考虑用任务队列来实现这个事,这是一个非常好玩的解决方案。

这个呢是非常好玩的解决方案,来看这里看这里,我们讲最后一种解决方案吧,好不好,最后一种解决方案,然后我给大家介绍课程,OK介绍课程,介绍课也没关系啊,你也可以说一下你的情况,我帮你做一些职业上的规划。

也可以,来看这里,这个这个是特别好玩的一个解决方案,这个方案用到了一个任务队列,任务队列有好多好多种,从数据结构角度讲,有数组有链表,有各种各样的容器,有哈希表,那么呃从那个阻塞非阻塞的角度讲。

有阻塞有同步的,有非同步的啊,听说有带权重的,不带权重的这种的这种的队列呢非常的多,要想透彻理解线程池,就是任务队列这块必须得理解,理解到位才可以呃,所以它是有优先级的,刚才有同学想说说线程池。

我今天要给你讲,到线程池就得把任务队列给你讲完,但是我们可以聊一个比较好玩的队列,这个队列呢叫做transfer to transfer you,你们还在认真听吗,还在认真听老师扣个一,Good。

OK好好听我说啊,这个trans的Q是一个特别好玩的Q,他是个队列,队列呢就是个容器,记住这是个容器,好这个transfer呢它是一个非常好玩的容器,你可以认为它是一个,他是一个必须往里头装的东西。

伸着手扔进去,必须等人拿走,往里装的手才能出来,就是怎么说呢,你可以认为它是一个容量为零的队列,容量为零的意思不是说你真的装不了东西,而是说你装进去东西之后,像原来啊我们装一个往里队列里扔个东西的。

这个县城,往里头扔个馒头啊,扔坨便便,你总是扔进去之后,我就不管了,我就走了,我该干嘛,该跟学生继续扔,但是这个队列transfer transfer cute,它的好玩的地方在于。

你往里头扔了这坨便便,必须得等着收份工给他收走,你往里头扔个馒头,必须得等人拿走,把它吃了,你才能够这个线程才能离开,才能继续往下运行,所以它自带自带阻塞的功能,这是他的队列比较好玩的地方。

叫transfer cue,这个Q啊,也是这个队列呢,也是理解线程池非常重要的一环,线程池里面有一些常见的线程池,就是用它来实现的,我想有一个任务扔到我县城池里之后,必须得有人替我执行了,我才我才放心。

用什么,这叫可靠吗,不是说消息消息队列的时候也需要研究可靠吗,一定要这个消息被消费掉了,这个东西可以理解为和这个类比的,来这边能听懂的了,扣一。

LEON和那个县城池synchronized q是一个东西吗,线程池里面的synchronized q是通用的叫法,这是同步队列之一,嗯好可靠,这可靠这件事呢,当然他跟那个我们普通的说的消息队。

Rock mq rubim q,然后active卡夫卡不不不是那个意思,好这里的可靠呢是另外一种可靠,就是说我这县城只有等别人消费完了,我才能继续往下执行,你不你不给我消费,我就不走。

好这个队列呢有一种方法叫take take的,意思是伸着手往里头拿东西,比如说这个队列里面如果空了,如果这里面没东西了,那么你这个伸进去的手是不会出来的,我必须伸进手去,必须拿着东西我才会走。

这是消费者,而另外一个呢叫TRANSF,transfer的意思是,我必须有另外一只手,把这个东西给他传递进去了,而且另外一只手拿走了我这个线程才能继续,所以它自带同步功能,那这事就不好玩了。

好玩的地方在于什么呢,好玩的地方在于注意看我有两个线程,第一个线程我会把我的字母传进这个队列里,或者叫传进这个容器里传进去,这是那个容器,我会把我的字母传进去,C传进去是被谁拿走了。

被另外一个县城拿走了,被T1线程拿走了,T2先把字母传进去,被T1线程拿走,T1线程take拿到了这个字母之后,直接打印诶,结果你发现非常好玩,本来应该打印数字的,它是从队列里把这个东西给拿出来。

拿出来之后打印的是字母,而本来应该打印字母的,他拿到的反而是数字,就互相之间把我该有的东西,我把馒头递给你,你把萝卜递给我,你去打印馒头,帮我打印馒头,我来帮你打印萝卜,这叫它好玩的地方。

比较吊诡的地方,你们如果到过内蒙古的集市,到过新疆的集市,你会发现在卖羊卖骆驼的时候,都有一个套管,一根管子套在两个人的袖子上,然后大家伙两只手伸进去,我出两毛不行,攥住你的两毛五,我出一毛五好。

必须把这个手递手的递过去,程序才能继续往下运行,好玩的地方,T2放进去直接拿出来,拿不出来,没有这个方法,只能穿法,没有往外拿,这是比较好玩的一个啊,挺好玩的,当然还有其他各种各样的解决方案。

你可以自己去琢磨琢磨,怎么交替呢,还没意识到怎么交替啊,我这个县城把它扔进去,你没有拿走之前,没有拿走之前,是我是不会继续往下的,能听懂吗,我是不是得交过去之后,你就直接就直接把它打印了吗。

take可以认为这个take和这个同时执行的开,只有我这个打印完了tag之后,我才会给你传另外一个,所以你放心你,你在你在哪等你,你先把把你的传给我,你在等着我再传给你。

这个过程一定不会前后有有有交换啊,所以他就交替执行了呀,这不就交替执行吗,这两个谁先执行的,你拿count down let来控制,我只是省略了这步,谁先执行,有什么关系吗,我刚才不教你,教你了吗。

想控制哪个先执行,Count down li,怎么着还得每个都重新解一遍,嗯好了,回顾回顾我们今天讲的内容啊,今天给大家简单聊一聊,就是因为我我讲课有时候讲的比较深,偏深偏深。

就会发现有小伙伴他这个未必能跟得上,未必能get到,所以呢今天呢实际当中讲课呢,我一般会从那个应用级别的开始慢慢讲,然后慢慢再讲到原理及,应用级别的是吧,我们聊了一下这个什么cs。

什么cs a b AC a s的这种原则性的保障,聊着聊呢,呃比较经典的这种同步机制,就是sychronized with notify,以及他的问题,为什么他会被lock来替代。

为什么会被reaction lock来替代,嗯我们聊聊门栓这玩意儿啊,summer简单说了一下概念,没有聊cliberia FA exchanger,没有专门说,当然其实这些东西都相对简单。

比较难的地方点在于底层实现,底层实现,比如说我刚才说的任务调度算法,你一聊线程一定会聊到任务调度,医疗任务调度比较牛叉的人就开始问,就开始问你cf s,你不信你试试。

然后面算法的基本上就是l r u lo fu,你不信你试试去啊,你不玩不把这个玩通了,想去大场面费劲,就算你面积基本上蒙的成分居多,也可能那个面试官自己就不懂,因为以前是这样的。

有一些面试官他是不是非常专业的程序员吗,别的行转过来的,这个在以前的很长的时间段里头,这个现象是存在的,但我觉得以后会越来越专业啊,以后一定会越来越专业,最开始的时候鱼龙混杂。

后面一定是越专业的人生存能力越强,新星同步锁的原理,这个来不及讲了,就cs跟大家说了,AQS这个就相对相对难好多啊,这是需要你自己去读懂了这些锁的源码之后,这些锁就是用它来实现的,然后再去探究它。

就我在VIP里课里有讲好了,介绍课我刚才说过啊,就是这个整门课呀,我们大概自己是自己,目前是把它分成了大概四个阶段嗯,可以用钱来划分,也可以用职级来划分,我们先聊聊职级的吧,P5职级我我先告诉你啊。

P5P6本质上是同一职级,P5职级是入门级别的应届生,P5,P6职级是说在社会上工作了大概3年以内的,3年以内,3年左右,这个时候进P6最合适的,5年左右要考虑P7,P7这件事相对来说就难好多。

当然你进不去,你也只能拿P6薪水拿上就行,然后呢真正做到无中生有,真正做到对行业有影响,才能到P8,这个比较难,超级难,不过没关系啊,我还我觉得还是那句话,就学东西呢,我们一定要学牛逼的,学有效果的。

雪讲的比较深,比较长,比较多的,学老师比较多的,学老师比较牛的,这样才能够做到降维打击,你懂吗,整个课的效果我一会跟你说,简单说,老师这里的,今天讲的内容叫高成知识体系里面的一部分,一部分课的一小部分。

这部分内容还比较多,段正明白JMMJVM操作系统原理,我不念了,好吧,就这么跟你说,基本上市面上的这种,你看到的那那那那那些常见的这种课,这里全有,而且讲的非常深入,hdp have就是大数据相关的了。

就不说了啊等等这些问的知识点,后来有学员说那个老师知识点呢我够使了,但是我还想积攒项目经验,老师怎么办,八大项目从适合学校学校的学院的级别的,到到到到这种比较高级的啊,到分布式微服务的。

到excel的啊,现在有同学开始落地了,到推荐系统到中台啊,到流式计算,还有其他项目搞定,大概啊,我刚才给大家看到,我们整理出来的入门级别的版本,这部分这部分搞定你差不多020,025到30P5。

直击这样,这部分这两部分搞定差不多30~70,想往上再涨的时候,就需要学更新的更高级的内容。

这也是需要你你是降维打击啊,要想做到降维打击,学点男的,不要老学女的,这哥们儿是两个月,我让他从55万干到70万嗯,37岁好吧,他原来是做PP的,这哥们儿三个大狗大厂,三个超过700000offer。

要求严格保密,的8月25号报的名,拿了三个70万年包的82万年,报的75万年包的无人车配送,琢磨琢磨哪个公司你应该知道啊,无人车配送吗,这哥们儿原来年薪是七十七十,大概看了咱们的课程之后。

当然他这个本身能力也比较强,然后做查漏补缺,120代人,120万年薪课程的帮助当然挺大啊,一定是比较大,只要你听话就说。

如果说你不信老师,这个就没招了啊,凡是敢给于老师信任的,其实到最后这就是他们的效果好呃,其实到120的讲东西东西就比较多了,我就不会在这里给你一一念了,可以这么说啊,那个从基础到算法到底层的源码嗯。

李老师讲的源码课,现在大概讲了20节课,接近40个小时,spring的源码只讲了一半,还有一半把这一堂源码,一门源码课听懂搞定,你在面试官那里,那就是神,听过的都说好好,然后最重要的想70万到120万。

架构师要能落地,什么叫落地,这个就叫落地,我们搭建自己的私有云平台,在这个平台上搭建几十台机器,上百个节点,撑住千万级并发这样的一个系统架构出来,把这个系统架构搞定,并且能落地,百万年薪向你招手。

这是我们已经开放的云平台,好对不起,他好像是好像是换了换了位置,我们的云平台,云平台在哪里。

坏了是因为他密码忘了,忘了新新的名单都是记录在这里了,看看老的音频单还能用吗,这是老的这个云平台啊。

我们现在是有两套的,在线的这个实验运营平台,一套呢是基于,KVM另外一套是基于容器的,就基于虚拟机的和基于容器的,这是我们老的那套,老的那套应该是在撤了啊,我我我我忘了问我们李老师,那个新的那套在哪里。

就今天就不给大家演示了,就是你呢你会发现可以这么说啊,你在任何地方基本上都找不着,你自己能手工搭建几十台的服务器,说这些节点作为分布式id,这些节点处理分布式事务,这些节点产生分布式锁。

好把这些个所有的有机整合到一起,中间是怎么进行熔断降级,限流监控压测全链路的追踪,把这些个全整合到一起,OK你是架构师,我们才认为你是合格的架构师,所以从入门到入坟,在这里全帮你包含了,最重要还有一点。

还有一个叫黑卡,黑卡是什么东东诶,看这里,就是我们今天的活动黑卡是什么意思。

黑卡是我们俱乐部的终身会员,是我们app的终身会员,是我们MC课程的终身升级版,也就是说以后我们升级你是不用掏钱的,注意我们每年都升级,我们时时刻刻在升级,我们每周讲几十节课。

系列 5:P29:29、Spring源码基础讲解 - 马士兵学堂 - BV1E34y1w773

来先说第一个吧,spring spring啊,我就所有人在用吧,在公司里面你们可能会用spring boot。

可能会用spring cover,无所谓什么技术,但是它最终的底层基础支撑都是我们的spring吧。

而且每个学生在刚接触框架的时候。

基本上都是spring开始的,那面试的时候经常会问到一个问题,说来你给我谈一下你对spring的理解。

当问到这样问题的时候,告诉我怎么回答。

有思路吗,我们还是一样,我们我们围绕着面试来说,好吧嗯嗯谈一下你对spring的理解。

这个怎么说,怎么表达呀,很多同学啊其实是非常害怕。

或者说惧怕这种宽泛性,这种问题的在我看来。

我觉得这东西啊它是非常容易的一件事,为什么,因为你答的东西只要跟spring沾边。

都不能说你错,那个同学在面试的时候经常会怎么表述,基本上会提到两个名词。

第一个是LC,我们叫控制控制反转。

第二个叫什么叫AOP叫面向切面编程,然后呢,你们可能会描述一下。

LOK好解决什么样的一个问题,AOP解决了什么问题,然后到这个环节的时候,基本上戛然而止了。

我告诉大家,你们以这样的方式去表述,百分之百是不对的,所有同学老师。

我在IOC的时候还会提另外一个东西叫DI,要提交一些名词。

这些名词告诉大家,谁都会,你要凸显的是什么,你与别人不一样的地方。

所以你在你这个问题的里面,你要贯穿进去。

你对于整个spring体系的理解,那么在回答问题的时候要怎么去回答,告诉大家一定要回答一种方式叫总分。

什么叫总分,先说明清楚好吧。

总的spring的理解是什么样子的,你可以说spring是一个轻量级的框架。

好简化我们的开发,明天重点包含两个模块,一个两个功能。

一个叫IOC,一个叫AOP,IOC叫控制反转,原来我们在使用对象的时候。

必须要自己去new好吧,然后才能进行调用,现在使用LC之后可以干嘛呢,由容器帮我们来创建对象。

并且由容器来帮我们管理对象对吧。

减去我们很多的一些呃,开发代码上面的一个成本和,提高我们对应开发的一个效率。

LP叫什么叫面向切面编程,什么叫面向切面编程呢,我们在使用的时候,需要嵌入一些跟业务无关的一些核心代码的。

时候,可以在a OP里面进行操作,比如说日志权限的增加。

都可以在a OP里面进行操作,很多同学基本上这样描述。

你聊完之后就结束了啊,这样说我不能说你错。

但我只觉得这样说不是特别完整,那么下一步你要紧跟着说什么,这上面是对IOC和a OP的解释。

那么紧跟着我希望你能说出对于spring它的理解。

那spring是什么,说完这些点之后,你可以加一句话,其实在我看来。

spring的本质是什么,是一个容器,虽然我们把它当成框架来用。

但是呢基本上是容器好吧,除了容器之外呢,我C还有一点是我自己的理解叫生态。

因为我们现在在公司里面用的主流的框架,基本上都是在spring的基础之上。

上层框架,比如说spring boot,Spring cloud。

Spring data,Jpa,spring security等等,一系列相关的一点好,这是它对应的东西。

那么我们要了解的是什么,在整个spring里面,最关键和最核心的就是我们整个IOC容器里面。

如何帮我们去创建好吧,以及管理对象的。

那么这里面必不可少的,要涉及到我们的什么bean的生命周期问题吧。

你是不是可以把bean的生命周期带出来,再带到bean的生命周期的时候,你可以提到spring源码里面还有哪些具体的扩展点。

提到扩展点之后,你必然会提到一个东西叫being post processor。

提到并post processor之后必然会提到a OP。

提到IOP之后再解释a OP的详细功能,能理解我刚刚说的这个思路吗。

能力的来给老师扣扣一,能听懂吗。

就是什么叫体系性回答,你要给别人展示出你自己不一样的地方。

怎么去展示,因为一般同学基本上回答完这个东西结束了。

你不会有自己的理解,那后面你要去贯穿上你的理解,什么bean的生命周期的对吧。

AOP的一些简单应用了的实现原理了,这些东西把包括动态代理对象啊。

这些东西你是可以能输进去的,你要把它揉到一块去,给没给面试官的感觉是什么。

这个人还了解过源码,或者说看过源码,或者说对这个基础框架是有深入理解的。

要给人这样一个感受,明白意思吧好吧。

这样的话你的薪水才能高上去,但如果说老师我对这东西不理解,我到现在对于spring也简简单单的就是一个会用。

哪怕我对应面,就是面试中问到我那个B的生命周期问题。

我都是提前一天去网上搜一个帖子,我背下来了。

我把它背完之后对吧,我去面试官给面试官说,至于你说的那个扩展点,我压根不知道是啥。

这个别慌,今天这节课我们第一个点,我先帮你去把整体的思路给你贯穿起来。

好不好,坐下面哈,好好听课啊。

来我刚刚啊已经做了一个范本了好吧,有兴趣的同学下去之后。

可以把我刚刚说的那套东西好吧,整理成一个文字描述,然后自己往里面填肉,把把各种细节都填充完整了,那下面我要说的是什么。

是整体的ring框架的实现原理,LOK的整体的实现机制好吧。

spring怎么解决循环依赖问题,这个是一个比较大的问题。

明天我会专门拿出一节课来表述,别着急好吧,什么画图软件叫枫叶云笔记好吧。

这个画图软件大家如果想要的话,可以去下载一下好吧。

工业云笔记。

系列 5:P3:2、程序中最难调试的BUG:野指针和并发问题 - 马士兵学堂 - BV1E34y1w773

我告诉你程序之中最难调试的bug就来源于这里,程序之中最难调试的bug,一个是野指针,一个是并发问题,这两大问题是程序之中最最难以调试的bug,好解释一下什么叫野指针,野指针的意思是很简单,同一个对象。

释放了两次,好这是什么意思,不能说呃,Sorry,不能说,释放了两次,就是同一个对象,同一个对象,两个指针一个释放了,另外一个不知道还拿来用,或者说虽然说同一个对象是可能是同一个指针。

或者说是同一个指针,不同位置,其中一个其实这个对象已经释放了,但是另外一个指针的另外一个位置的指针,不知道,另外一个县城里面的指针不知道好,它依然还在使用,这个是野指针,就是不再指向任何对象的指针。

这就是著名的有一个异常叫now pointer exception,呃如果你原来学过C语言,C加加语言,经常的这种东西会引起内存的崩溃,我告诉你,这是所有语言所面临的最难调试的bug。

包括java这个东西是怎么产生的呢,非常简单,给大家看看这张图,为大家再稍微画一下,再看这里简化一下,同学们听我说,我不管你是任何的语言,假如说我们有两个指针,Ctrl c ctrl v,要O了要P吧。

好看这里假如这个O和这个P这俩哥们呢,同时指向的是同一个对象,那么如果我们程序执行的时候,比方说我在main方法里面要把这个对象给干掉了,或者我在M方法里面把这个对象给干掉了,给他删了。

那我问你妹方方面的这个小O,它指向的是个什么东西啊,指向的什么东西,java就叫地址,没有指针,java叫引用,本质上就是指针,好吧,我们谈本质啊,不要谈那个那个那个你你不要咬文嚼字,你不要学孔乙己。

非得跟我矫情回字,有四种写法,这个东西没意义,理解什么意思就行好吧,玩文字游戏是最没劲的,这时候这时候就变成空值了,对不对,更有甚者,你这块删了之后被别人给占了,你想想看会发生什么,会发生。

你指向了别人对象,也许你操纵,我告诉你,你拿到了别人的这块内存里面的东西,以前啊在内存里面偷别人密码,就是这么干的,嗯好好听,我说,这是程序史上最难调试的bug,就是野指针。

这个指针指向了它不该指向的东西,他特别严,这个这个就叫野指针,不知道我说清楚没有嗯,C和C加加里面呢是永远要面临这个问题的,也许一不小心你这边删了另外一个指针,还在使用它。

也许你这不小心这边删了其他的程序,或者说其他的程序的部分内容,又又又又占用了这块空间了,那么这时候你另外一个指针指向了它,不该指向的内容好了,我现在并没有聊java语言,我现在聊的是所有语言。

就是无论是什么什么语言,都要面临这个问题,你要正确的删除这块空间,不能多删一次,也不能不删,还得保证你删完之后,所有人都用不了,好吧,这是非常非常难的啊,我告诉你,这是第一。

这是第一种特别难调试的bug,历史上这种bug维护起来超级超级难,你知道go语言是怎么诞生的,go语言是原来google为了替代他们以前写过的好多,C语言的程序,C语言程序写起来也许比较容易。

但是维护起来超级麻烦,bug调试起来特别特别困难,所以他们开发了go语言,go语言呢,不再用手工的方式去维护这些内存空间,而是调用也跟java一样,引入了GC,当然这是最难调试的bug之一。

那么第二个最难调试的bug是并发问题,我觉得这个问题稍微一说你就明白,就是多线程,访问同一块,内存空间,如果这个并发问题,再加上野指针问题结合起来的话,你调试起来就更麻烦了,这里只是一个县城站。

完全有可能我还要来,另外,另外的一两个这个是非常有可能的,你想想看,行了,这图不太好画啊,这这图呢不太好画,缩小一点,这哥们放这边来,完全有可能发生一种什么情况,我这个县城站里面啊。

也有好多好多的指针好,我指向了这个对象,也许是我这个线程把这对象给删了,也许是我这个线程访问的时候,我俩同时开始写,造成了数据的不一致,好了,我告诉你,像这样的问题,调试起来是最最头疼最麻烦的。

不知道大家有没有这方面的体会,当然有同学说老师我天天写CROD,我是没有这方面体会的,那就没招了,这也是为什么你呃,你你你你你你你不应该不能关,只关注CRUD的原因,因为面试里面好多好多的问题。

都要牵扯到这方面问题了,好吧,嗯所以所有的程序啊,最难调试的bug基本上就这两个,这是最难调试,一个叫野指针。

系列 5:P30:30、spring加载bean的过程及框架的扩展 - 马士兵学堂 - BV1E34y1w773

好吧来接着来讲我们的spring spring最开始提到之后,第一点它已经是个什么容器了,好吧,容器干嘛的,用来装载东西的,比如说我们的水杯水壶水缸对吧,对于我们的应用程序而言,它用来放什么。

放我们的定对象,当然里面可以放一堆的,比对象不只是一个N多个好看,你个人的一个需要先放多少个,放多少个,那这个时候你想我们如何去把IOC给它,融融融融到一块呢,IOC是个容器。

我们可以把整体这个框框认为IOC容器里面,B对象它是如何帮我们去创建的,或者换一句话说,谁能告诉我,spring是怎么知道你要去创建哪些对象的,怎么创建,先不管他怎么知道我要创建这个对象啊。

通过什么来知道好,同学们通过什么cam,也就是说我们其实是有一些方式,可以让所有人感知的,比如说最开始学习的时候,很多人接触的时候用的是XM2,上面配置文件嘛对吧,然后后来呢大家可能为了简简简化操作。

我们更多用的是注解,不管是长毛也好,还是我们的注解也好,包括我们的配置类也好,这些方式里面它都是定义好了,预先存在的并对象,当我把这些bean对象定义好之后,然后我叫容器来帮我管理。

那这里面定义的到底是个啥呀,对像零零后的程序员可能都没有写过XM,因为现在很多机构讲课的时候,基本上都是直接以配置文件,直接以这个注解的方式来讲,但是坦白说我这提一件事。

我还是希望大家能够好好的把XML文件这种方式,理解一下的,因为它是根,它是本质,如果你能把XML文件的方式理解的很透彻的话,对于注解的方式更容易理解,好吧,我问一下上面文件也好,数据也好。

它里面定义的是啥,比如说老师定义的类定义的bean吧,其实这里面定义的应该怎么说,它叫bean的定义信息,我希望你们这么去描述它叫bean的定义信息,比如说老师什么叫bean的定义信息啊。

我们想创建出一个对象的时候,如果用反射的方式的话,我必须要知道他的一些信息吧,写一个案例吧好吧,比如说我要随便写一个配置文件,对于很多零零后没见过小孩,我给你们写一下好吧,写有很多零零后程序啊。

你不要觉得这是很难啊,比如写一个叫beta sclass,等于com点回味一下这种方式,第一data,boss可以这么干嘛对吧,然后脚下之后里面会有我们对应的property属性。

name等于写一个手机号,然后呢value给一个叫dollar大括号BDBC点username,当然里面还可能包含一些其他的一些属性值,对啊,我这不写了好吧,然后最后再来一个闭合标签。

这不就是我们变的一个定义吗,像这样的一些定义,什么叫bean的定义信息,比如说里面的什么ID的属性了,class属性了,name的属性了,value属性了,这些东西都可以成为定义信息。

我只获取到这些完整的定义信息之后,我才能够去创建出一个具体的并对象,在这里面会涉及到TMA也好,注解也好,其定义的都是这样的,BB信息,有了这些病信息之后,我会干嘛,我要预先把这些bean的信息。

加载到我们整个容器里面去吧,因为加载完成之后,在容器里面我才能够去把对象给创建出来,如果不在不加载进去的话,在外面放着,我是识别不到的,所以我是必须要有这样,当前这样一个加载过程的。

因此在这个地方你可以怎么写,在spring里面,它提供了一个默认的接口,用来承载这些具体的信息,比如说叫B,所以你看这个单词的名字,你能猜出来它翻译过来不就叫BD定义信息吗,是不是这意思。

注解也是一样的,注解最终在解析的时候,也要把它转换成一个b definition的对象,然后我通过各种方式,可以把我们的XM2加进来,可以把我们的注解加进来,最终都组装成这样一个对象,这没问题吧。

来到这块能听明白,同学给老师扣一,能听懂吗,没问题吧,那有没有同学会好奇啊,老师我这样QM文件是如何组装重叠对象的,如果是你让你来实现,你现在有一个XML文件,你怎么把它组装成这样的对象,能做吗。

可不可以做,可以吗,第一步,刚开始我是插画文件开发文件,有了之后可以干嘛,是不是可以把这些读文件给读过来,你告诉我读文件用什么方式,读文件用什么方式,IO流IO流的方式把它给读取过来好吧。

读取回来之后先把它放到我们对应的内存里面,放内存之后别忘了它是内存里面的一个数据了,紧跟着要干嘛,说白了,拆包文件里面放的东西,在我看来就是一堆字符串,那这些字符串。

我如果想把这些字符串给充分的利用起来的话,我要怎么做,说好的对象,那你别忘了,XM文件是一种非常独特的,具备特殊格式的一个文件,所以在这里面我可以通过什么,比如说FAX对吧,比如说dom qua。

这样的方式,我是不是能把XML文件转换成什么东西,叫document文档类型吧,当我有了这样一个文档类型对象之后,我是不是意味着里面就包含了对应的父子节点,对吧里面一堆的什么note node对象。

有了note之后,我能不能通过循环的方式,把node里面的每一个属性值,属性名称把它取出来,取出来之后我能不能设置到我们对象里面去,设置到BB中,可以这么做吗,可以吧,这个流程能听懂吧。

如果让我们自己操作的话,我们一定会这么干,其实源码里面也是这么做的,跟我们想的东西是一模一样的,只不过很多同学没看过这些源码,所以感觉这东西好像很难的样子,其实不难,你就按照你传播的手段做操作就可以了。

BD是啥,BD不是bean definition吗,我这儿我这儿写不下了,所以我写了个BD叫bean definition,好明白意思吧。

如果大家不信这东西的话,我们可以来验证好吧,再验证呃,我问一下有多少同学在私下里边自己看过源码,给老师扣个一,就自己尝试看到过这个东西,不是让你在项目中用的,是帮你帮你把这个流程梳理清楚。

你面试的时候能跟面试官吹牛逼,懂我意思了吗,不是让你自己在项目里面用的,一般也接触不到,好吧,如果你看过源码的话,你应该会知道好在源码里面很多人在看的时候,基本上会提到一个非常重要的类。

叫abstract application context。

在这个类里面会包含一个非常重要的方法,叫什么呢,叫REFLESH,之前有人说过一句话说,如果你把REFLESH的流程看明白了,那么你对spring框架理理解到位了,我们不带你看这东西啊。

我带你看到处理那个配置文件的那个地方,他是在哪做的,回答,你看这个东西叫load bean definition,叫加载bean的定义信息,点开里面我们一直往这边看啊,选它天猫。

然后选择这个选择这个选择这个,然后ACG选择,你不用跟上我的速度啊,无所谓,我对这东西很熟了,所以我打的很快,你们可能跟不上啊,跟着往下听就行了,我带你们找到具体的地方来往,这看到这行的时候。

你告诉你看到了什么东西,这样代码能看到吗,比如说我们写在外面的XML文件,会把它变成一个resource的一个对象,然后我通过这个result对象可以读取我们对应数据,所以这样获取到result之后。

第一步获取到我们的input stream是吧,引流了,当我引了流之后,我开始对这些流进行相关的一个处理了吧,不要把数据进行处理的那么点进去,在这一刻它有个东西,把刚刚的put source。

input source里面是个put stream stream,拿出来之后,把它组装成一个什么东西,啥是我刚说的document的,不管你是通过SX也好,还是通过我们的端口PJ也好。

把它转换成一个document文档,没问题吧,当我有了文档之后再干嘛,文档是包含了父子节点关系的,就在这里面我会干嘛呢,解析出我们具体的父子节点关系,是不是可以通过循环点进去看这块儿诶,哪去了看看。

那我开始获取到他所有的子节点,有了对应的子节点之后,我可以把每一个节点取出来,取出来之后我看一下,我是把它当成一个默认元素进行解析,还是把它当成一个用户自定义的元素进行解析。

是不是数据流程跟我刚刚写的一样吗,一样吧,所以你们在看原版的时候,同学们注意了,为什么很多同学看源码看不懂原因在什么地方,你看源码,你就真的是在看源码,而不是说我在思考这东西,如果是我的话。

我会怎么来考虑这件事情,或者我会怎么来创建对吧,别人写的方式比我写的方式到底好在什么地方,这是你需要去对比思考的事情,你带着思考去学习,和你直接跟着学习,效果是完全不一样的,明白意思吗。

来这块儿能碰到同学被老师扣一,慢点吧,那不学怎么做注解一样吗,我识别到你的类上面加了一个at component,at service好,at repository好吧,At control。

这样注解的时候,把具体的类对象给你识别到识别,到时候把它装成一个BD对象之后,我把这些B对象来生成我们的具体对象,不就完了吗,一样的流程一模一样好吧,但是你还要去做一件事情,同学们弹幕上转完之后。

看起来我们好像已经把这个流程给结束了,结束完之后紧跟着我该干嘛,叫创建对象对吧,我问一下,在框架里面创建对象一般怎么创建啊,怎么创建,能创建吗,反射吧,基本上都是反射。

很少有人用new的方式来创建我们这个对象,基本上反射,因为反射它足够灵活,能满足我们各种各样的一些需要啊,配完对象之后,我可以拿过来直接用了,看起来就说好像很简单,那这个时候你就要思考了。

为什么这个地方在写的这个配置文件好吧,它定义成XML文件,话说如果我把它定义成一个properties文件行不行,给我定义一个配置文件格式,这个配置文件格式呢叫properties。

我的properties里面,能不能也把它装成一个预定对象,能不能可以吧,那你告诉我properties和TM的区别在什么地方,不就是两种文件的解析方式是不一样的吗。

我只要配置好对应的properties,它的解析方式不就可以了吗,用解析properties文件方式解析它,用创号文件的方式解析它是不是可以,那同样的刚刚说的用压码是不是也可以对吧,我能不能用JON。

是不是也可以,我只要能解析好它对应的关系不就完了吗,其实很简单,那你在这块你要去思考什么东西,同学们想好了不同的定义方式,需要有不同的什么解析方式吧,我要不要给他形成一个统一的规范,因为在我没读取之前。

我其实并不知道我的配置文件是哪一个,是不是这意思,我在这块我是不是可定义规范,写东西叫定义,约束规范对吧,所有啊需要进行解析的操作都要实现直接跑,可以不,那这样的话,不管怎么样,我后面如果有其他。

如果有其他新的配置文件,我是不是也可以实现这个接口,只要分配好接口了,我匹配好对应的类了,我是不是可以把对应的实现类或者解析类,给它冲进去,我是不是就可以解析对应的配置文件了,这块能理解吗,能理解。

给老师扣个一,能不能理解,所以这就是,为什么源码里面要提供这么多的接口,这么多的抽象类里面的原因,我要定义好对应的约束和规范,那同样的在源码里面,这块会有一个东西叫什么叫并definition。

reader好包含这样的一个对象。

当你有这样的一个对象之后,我们可以来看一下小b refer。

它是一个接口啊,你看接口之后,我定义好对应的方法,我只需要去实现具体的子类就可以了,那这样的话我根据我不同的子类,我就可以进行配置进行识别,并且对不同的配置文件进行相关的解析工作了。

这句话意思吗对吧,所以这个地方其实在源码里面,你在看的时候注意到像spring里面有7000多个大类,里面有很多的接口,很多抽象类,其实都是为了方便我们进行扩展栏使用的。

只不过我们平常在做业务开发的时候,你用不到这些扩展点,仅此而已,但你不能不理解其中的扩展,因为一个框架能够流行起来,或者说能够被绝大部分人认可,最关键和最核心点就在于它什么,它的扩展性能懂我意思吧。

所以我希望大家时时刻刻把这两个字留意起来,我问一下,如果你们需要在框架里面做扩展的话,可以用哪些扩展方式,或者我们自己在写我们自己的业务逻辑,代码的时候,可以用哪些扩展点有吗,能想到吗。

刚刚我说的接口是一个还有吗,不要说BPP和BF p p可以看,听过课的同学,听过课的同学可能知道什么叫P和BBFPP,没听过的同学可能不知道什么叫BBB,B和BFPP,比如说模板方法这种东西知道吗。

设计模式。

设计模式不可以扩展,像spring里面还有很多这样的扩展点,我给你看一个,再找一个吧,看这里面我们找到我们刚刚说的那个,reflect方法,在rap方法里面一共包含了13个方法。

你点开这个方法里面有任何子类实现吗,没死的时间吧,所以他这个东西干嘛的,就是留给子类进行扩展的,再比如说往下看这个on reflesh,这直接告诉你叫for subclass。

Do nothing by default,我留好这个口,你说这个口之后,我就可以在这里面实现我具体的业务逻辑了,那这样我问一个问题,你们都是有经验的开发程序员对吧,这个地方有哪些扩展事件,你知道的。

有人知道吗,哪些地方用到这个on reflesh方法了,有没有人知道,对在spring boot里面内嵌tomcat的时候,是不是就是在on reflesh里面进行操作的。

是不是你要发现这些东西的关联性,我为什么说spring是基础,是生态,因为很多上层的建筑和上层那些框架,都是在spring的基础之上做了一些额外的扩展功能,你现在就可以自己看。

在spring boot框架里面好吧,这一块就是用来创建我们对应的tomcat server,tomcat server就在这个步骤里面完成的,这不就扩展点吗,默认的时候还是什么都没实现,就这意思哇。

听懂了吗,来这块听懂的同学给老师扣个一,能不能理解,我需要我带你们看一下spring bot里面怎么扩展的吗,有需要的吗,希望嗯,我打开一个项目好吧,可远了,随便打开一下午吧,我带你快速快速看一下。

这个这个这个这个这个东西好吧,怎么看,打开你的启动类,改完成之后,这一个run多少,我就直接带你们找过去了,好吧,不一行一行带你们看了一行再看,太浪费时间了,reflect reflesh看了吗。

从这里面refresh1行一行,点的时候就能点到这个refresh方法里面去,依然是这个abstract application contest,然后在里面找什么找on reflesh方法,点击之后。

这默认实现没有,你点开里面太快了,从头来打到你六级debug启动起来好不好,我把启动起来,好了进来之后点F7进去好吧,找到new run方法进去,再点击run方法,然后听到它核心的启动流程里面去。

在启动流程里面,下面有一个东西叫reflesh contest,找到我们的reflesh contest,这行代码,然后点F7进去,再点F7进去往下走,点F7进到REFLESH里面去。

super refresh里面再点F7进去,我咱们今天课不讲spring boot好吧,我带你看看这个流程,你看下这有REFLESH,我刚刚在你们看的时候,这里面是不是也是REFLESH。

是REFLESH,两个地方是一模一样的,都是这个abstract application context,好,后面这也是abstract obligation context类是一样的。

只不过我在找的时候找到具体的实现不一样,我们往下走走走走走走走,什么意思啊,走走走到on reflesh这行代码里面去,然后点FC进去,这有一个super refresh对吧,再点去往下走。

有个create web server df,七进去往下走。

往下走,可空吧,等于空之后开始获取我们的web server factory,这一获取下一步告诉你了,当前的factory是什么,The tomcat sweb server factory。

有了这个factory对象之后,我就可以根据这个工厂来创建出,我们具体的什么,他们看到server了吧,是不是东西,所以我给大家讲这么多意思是什么,你有时间我给你们讲spring box源码好吧。

这个这个这个这个没啥难的,我想给大家说的是什么,你要知道它其中的扩展点在什么地方,你要知道这东西哦,而且你在看原版的时候,你要时刻留意这东西,就这东西你掌握好了,才是你自己的实力提升的点,明白了吧。

好吧对啊,废话不多说了啊,还是要跟着我学学的是什么,不是说简单把流程学会了,我希望大家学会的是什么方法,方法很重要,OK好了,我们这涉及到接口了,写完接口之后问一个比较low的问题啊,特别low的问题。

谁能告诉我这个接口和抽象类的区别呀,讲到接口了,我说了原版里面spring源码有7000多个类,里面一定有很多的接口和抽象类,接口和抽象类有区别吗,谁能说一下,单继承多实现,这个蜡笔没了。

小心你竟然听过我的课是吗啊,软件是在BW待过BW是吗,很多同学啊听过我的课,你应该会知道我强调过这件事情,虽然那个接口有什么,你们好多人刚告诉我什么单继承,我们多实现什么,不能写具体的方法。

代码什么之类的,这东西没问题,但我认为你们所说的这些点,统一的称为什么叫语法上的区别点,你在面试的时候,如果只去跟别人说语法上的区别点的话,不好意思,这东西谁都会,哪怕一个小白,刚学完之后。

老师也一定给大家总结了很多具体的东西,这东西不重要好吧,主要是什么,你要体会其中的设计思想,什么叫设计思想,接口和扩展类最主要的区别在什么地方写一下,接口它本身是一种叫自上,向下的思维模式,而抽象类。

叫做就这样,向上来,这样东西能理解的扣一,不能理解的扣二,什么叫自上向下,什么叫自下向上,之前说过乔尔同学比较多,我解释一下这件事情,你们之前在面试的时候,如果去给别人说语法上的区别,我觉得没问题好吧。

因为他这样区别没问题,但如果你想凸显的自己跟别人不一样,你要说这玩意儿什么叫自向向上,什么叫自向向上,这两个东西怎么理解,很简单,接口我们叫什么叫定义的,叫约束和规范,这意味着什么事,我定好了规则。

你的子类必须要按照我的规则实现来,没例外好吧,特效是什么意思,抽象类是因为你有了很多具体的子类实现,你把很多公共的特性拿出来了,变成了一个抽象类,能听懂这意思吗,比如很多动物动物有什么眼睛的颜色啦。

名字了好了,把这几个属性拿出来,拿出来之后,我变成一个抽象类,其他的具体实现子类我直接继承就完事了,那接口呢我定义好了,具体的方法实现,你就必须要按照我的方法规范来,你可以自己加,你自己加没问题。

但是我我写东西你必须要有,所以这个时候你理解什么叫自上向下,什么叫自下向上了吗,来理解的图一,所以你面试的时候你要给别人说这东西,不是说你们说那些语法上的区别,你说语法上的区别没有意义,好吧。

显示不出来你自己的技术实力,谁说不理解,下课之后你私聊我通项问你什么意思,接口你怎么定义的,你先定义了一个interface,里面有A方法,有B方法,有三方法,我的实现子类在实现了这个接口之后。

我必须要把ABC3个方法去重写,我可以自己再扩展一个地方吧,但是我必须要按照接口里面的,ABC这个方法来,所以它是自上向下的一种模式,我定义好约束你来实现就完了,而抽象类呢什么意思,我有猫对吧。

有狗有兔子,这边有一些公共的属性,比如说毛发对吧,比如眼睛,比如内蒙这样的名字,每个里面都有,我为了简化操作,我把这些公共的属性拿出来,变成了一个抽象类,我的子类只需要写自己独特的属性就可以了。

它是什么,它是共性的东西,它并不是定义了约束和规范,所以它是自下向上的,而结果是自上向下的,理解了吗,这东西啊,你们学基础的时候,老师应该告诉我们,那你们很多人基础老师不讲这玩意儿,你讲完之后之后。

很多人不理解,但你写这玩意写多了,你就理解了,明白意思吧,好吧行了,不多说了不多说了,这东西讲讲讲,扯的有点远,真没告诉我,你要你要去思考什么叫思考,对不对,好吧好了,内部之后,我们接着往下讲。

回到我们spring来收回到spring这块好吧,老实说背会就行,背会你体现不了别人的差距啊,我还是那句话。

系列 5:P31:31、spring的增强器的处理postProcessor讲解 - 马士兵学堂 - BV1E34y1w773

好不好好了,来往上收啊,回来之后来紧接着往上写,来往这来我们刚刚说了,刚刚经过我刚刚的讲解之后,我们其实已经把我们对应的XML文件和注解里面,定义的这些bean的定义信息,把它转换成我们的BD对象了。

有了BD对象之后很简单,我可以把对象里面的属性拿出来,通过反射的方式,我可以创建出具体对象,当我把对象创建出来之后,紧跟着下一步我是不是可以去使用对象了对吧,当我的对象使用完成之后,那简哥呢。

我是不是可以去销毁对象了,对啊,这是我们大概的一个流程嘛,基本流程都要这么定了好吧,从我们的创建到使用到销毁这个流程,这个环节能理解吗,你如果这样看起来的话,spring里面的东西其实还是比较简单的。

但是你想spring可能这么简单吗。

如果你真的看过源码的话,你可以点开它里面的统计,我刷新一下,你可以看一下它里面一共包含多少呢,包含了7000多个类,同学们,7000多java类不可能就完成这么点事啊。

他完成的工作一定很多,我们找一下java费用,你可以搜一下java,1412都累这么多类,对这么多对象,这么多代码,我不可能完成这么简单的事情,所以在框架里面还是那句话,最主要和最核心的是什么。

你要体会的是它里面的扩展性,这个东西,我今天啊不止一次的说过扩展性这些东西了,我希望你能把这三个字给我记到心里面去,因为这东西才是框架,或者说你自研框架的一些核心点,那这样我有什么需要进行扩展的地方吗。

或者说我需要进行什么扩展吗,注意当我们的spring框架它是跟我们的业务无关的,每个人拿到spring框架之后,你可能做比如金融方面的业务,银行方面的业务,保险方面的业务好吧,医疗方面的业务。

各业务点不一样,那意味着不同的项目里面会产生不同的需要,我作为一个跟业务背景无关的一个框架,我如何能够适配到这些所有项目里面去呢,对应着我在框架的某些点里面,我要把它加进去,非常非常多的一些什么扩展点。

让用户可以按照自己的需要去随意的进行扩展,把其随意的进行扩展,这点是很重要的,那这样有什么扩展点呢,来听我讲,我相信很多同学在看源码的时候,多多少少见到过一些类似于这样的描述。

叫post processor文件这个东西吗,什么叫post processor,见过吧,这东西怎么理解,有人把它认为叫后置处理器没问题,后置处理器更多是什么,是直接翻译过来的。

我上课的时候给我们的VIP前兆,我说这东西啊,你最好把它称之为叫增强器,它是用来完成某些扩展功能存在的,那在这个扩展功能里面有两个非常重要,或者说比较著名的接口,哪两个呢。

第一个接口叫be factory post processor,这是第一个,我们只说接口好吧,此类有很多说接口,第二个叫b post processor,这两个是大家见的比较多的。

同时给大家用的比较多的两个接口,那这两个建什么意义呀,或者说他们两个接口有什么区别呀,其实你通过名字你能够发现两个东西的区别,区分点在于什么,他们针对的操作对象是不一样的,这个东西它针对操作象是谁啊。

是不是BBC,好吧,那同样的这个东西呢,看到的是谁。

是我们的bean对象,是不是他们两个针对的对象是不一样的,但是不管你针对的东西是什么,最主要的点是什么,都是为了完成某些具体的扩展功能而存在的,这点是不可避免的,当然在这个里面还会有很多对应的扩展。

子类实现,比如说它依然会有些子类,什么子类,我写一下,里面有一个叫bean definition rtory post processor,它也会包含一些子类接口,实现子类接口实现我们就不说了啊。

因为这个子类里面有东西有很多,好吧,我们只说这些最关键的,所以你要知道什么,这两个东西一个叫bean factory post processor,一个叫bean post processor。

这东西我会挨个来给大家聊一下,可以来聊一下,好吧,来先说第一个,谁能给我解释一下什么叫being factory,什么叫bean factory,你们对于bean factory的理解是什么样子的。

谁能告诉我叫兵工厂吗对吧,大家一般人都是这么理解的,叫兵工厂啊,告诉大家,你翻译成兵工厂没问题,没毛病好吧,但是我希望大家看一下,原版里面对于bean factory的一个核心解释。

到底什么叫bean factory,其实并不是大家说的那个兵工厂。

可以来看看,它也是一个接口,再往上翻翻翻翻,翻到这行来翻译一下,The root interface for assessing a spring being container,什么意思。

root interface吗,跟接口干嘛呢,根接口呢用来访问一个spring并容器的根接口,也就是说我如果想访问一个容器的话,必须要通过我们的什么bean factory来进行操作啊。

就好比什么意思啊。

很简单,看好了,我这刚刚画了一个大框,这个大框我说的就是我们的容器,就跟你家的门一样,你家的房间影你家有个房间,你如果想进到这个房间里面去,必须要有门吧,没有门是不是要有个窗户,你才能进得去。

那这块是一个封闭的框子,我是不是也要给到一个对应的出入口,能方便我们对里面的属性进行相关的操作,所以这东西可以理解为什么叫FBATTERY,能理解吗,来能理解吧,给老师扣一,好吧。

那这个同学就会问老师不对,我在平常自己进行使用的时候,我很少会用到bean factory,我用的更多叫什么叫application context,因为我在写代码的时候,我基本上是这样干的。

怎么干的呢,叫contest,第2get bean,比如说里面有个对象叫我写一个person加class,我是这么做的,我通过这样的方式来获取我们的对象的,注意了,这个content是谁。

他翻译过来叫什么,叫application context,它也是一个接口。

那这个接口和我们的bean factory有什么区别呢,你看一张类图,你知道吗,application你可以把它翻译成上下文,没关系。

I这个接口你可以看一下这个接口,它诶它的类图标gram,这个东西它继承自定factory,所以并翻译叫什么叫根接口,所有东西,如果你想去获取到容器里面的一些属性也好,方法也属性也好,干嘛也好。

那些属性值也好,你必须要通过bean factory此类实现,只不过我在这些具体子类的时候,我提供了一些更加强大,或者说更加完善的一些功能而已,明白了吗,所以如果我想去敲容器的话。

我最应该操作的是谁,是我们的bean factory来关于这个bean factory,能理解吗,所以我会干干什么事,可以证明才行,Bean factory,其实完全可以把它等同于我们当下的这个容器。

因为我操作的时候,容器里面包含了bean definition,包含我们对象,所以这个东西可以等同于我们这的容器,但其实它只是一个访问的根接口而已啊。

如果你把这件事理解了,那么紧跟着你再看这个接口的下面的这些注释。

和下面这些翻译的时候,你就会体会到这样一个东西,往下看,说bean factory employment,说bean factory子类实现好吧。

food sport应该支持叫the standard bean lecircle interface,叫标准的bean的生命周期接口,什么意思啊,我的子类实现,必须要尽可能多地支持我的生命周期的接口。

好吧,他们the first set of insulation method,那their standard orders,意思他们这些初始化的方法,结合和他们的标准顺序如下所示。

你告诉我这块里面描述的是啥,描述什么东西,这坨描述啥不就是bean的生命周期吗,明白了吗,所以你们很多人都去网上搜一些,生命周期的东西,用搜吗,源码里面给你写的很详细,你有本事你把这些东西搞清楚。

你自然而然就搞明白了,明白意思吧,所以去看那些注释,它的注释很有意义,明白意思吗,所以你要把这东西搞明白了,OK当然分辨出去,这事一会我会敞开给你聊,不着急好吧,我们先回到这块,当然这个问题之后好了。

下面我就要思考了,那对于bean factory的扩展,我要怎么去扩展呢,很简单,举个例子,我刚刚在写了一个对象,写对象大家应该觉得很特殊,很奇怪,用在什么地方啊。

我这里面的这个property value,我用了一个东西叫dollar gdb c name,实际上我们知道我们在进行配置的时候,一般会引入一个外部的配置文件。

叫dB properties配置文件对吧,这个dB点properties文件里面,包含了我们连接数据库的四个属性,是不是这意思,那我问个问题啊,我们前面从cam文件解析完这些东西之后。

组装到bean definition里面去之后,注意啊,读到里面去之后,这里面的这个属性值会修改吗,会不会改,觉得会扣一,不会的,扣二会改吗,你们想想到底会不会改,肯定不敢骂你,这没必要去改它。

你这只是把原来我们写的tab文件也好,数据也好,完整的把它解决过来就可以了,那下一步我明明就应该开始创建对象了,你告诉我我要在哪去修改,我要从哪个地方去修改,所以在这块的时候。

就会包含了一个非常重要的接口,刚刚说的什么叫BEDEVI,post processor是这改吗,是不是我们可以来做一个验证。

好吧,来思考这个接口叫B。

Battery boost processor,对接口在接口里面上面有一定的解释啊,不管它是吧,然后点开它有一堆的实现子类,子类是非常多的,我这不带你拿一个看了好吧,我们直接点进去。

它里面有这样一个实现类,叫police holder configure sport对吧,往上翻上面里面做一件事,看这句话还是看注释好吧,看注释怎么怎么怎么去解释这个类的,跟这个接口。

他说这是一个扑向的基础类,没问题吧,这个图像基础类用来干什么事呢,叫属性资源配置,也就是说它是一个用来进行属性资源配置的,一个基础抽象类啊,那进行什么属性资源配置呢。

大家看叫resolve police holders in the definition,Property value,在B在FINITION里面的,property里面的value里面的单位服务操作。

你再看一下刚刚我写的东西,他是在BD里面吧,是在BD的property里面吧,是在bd property里面的value里面吧,我是不是要把这个值进行替换了,刚刚有人问我说,老师为什么要替换你。

下一步就该对象创建了,创建完对象之后,紧跟着干嘛了,该那个属性值的设置了,你不能把这个属性值设置进去啊,所以只能在哪做,只能在bean factory post processor里面做事。

能一同学给他扣一,能理解吗,当然这块你可以写很多个,按照你的业务需要,你可以写很多个,你想写多少写多少个,就有人会说老师你说的是真的吗,是不是真的,我们完全可以来做一个验证哦,我给你验证一下这个事儿。

为什么不在创建对象里面做,创建对象属于JVM里面的东西呢,你一个属性值得替换,要放到JVM里面做吗,就跟你出去玩一样,你出去玩的时候,你告诉我你要不要提前做一些准备工作,什么时候带好。

你把一些一些吃的喝的带好,这不是一样的吗,我要提前把这些属性做好吗,是不是意思,你不做好这个准备工作,你怎么去做做事情呢,就这意思,所以非常简单,你要把这个东西搞明白了。

那我们可以来做一个验证,做一个验证,怎么验证来,我带你们看一个代码,稍微出点再往上看,注意像这里面我就写了一个data source,没问题吧,这些data source里面出现的都是dollar吧。

都是我们的占位符,那我可以干什么事,我就g debug,debug之后,我们直接去跳过去,好听到内行,我们看看是不是在哪。

在我们的bean factory post processor里面完成这个工作的。

我先来验证一下,这东西很好验证好吧,这里面有一堆断点,把断点断掉,特殊搜索,大家来看看这块要注意了,我每次因为我编译的是源码,因为编译源码的时候比较浪费时间,有多少,编译一下好吧,来点MC进去往下走。

点F7F7,找到我们的REFLESH方法,然后往下走,往下走往下走,你进来慢慢走,不用管他跳过去就行了,刚刚这里没消完,拿走拿走到这步好了,当你到这步之后,我们打开我们的factory。

然后呢打开它之后往下找,找到一个东西叫bean definition map,这个bean definition map里面就是啥,就是我们说的那个封装好的必须对象。

所以我可以打开我们的data source,里面有一个property value,然后这个property value provide里面有provide list,找那个list你看到了吗。

是不是username,Password u 2java class name,你点开之后,你看看这个值是啥,他这个只有进行替换吗,同学们有没有替换,没有吧,我配置文件里面写的啥,对面是不是还是啥。

然后紧接着看往下一步做一个操作,谁能给我翻译一下这句话的意思是啥,这叫什么叫invoke,Bean factory tools,Processor,Invoke,什么意思,调用执行吧。

要执行bean factory post processor,来我们往下执行一下,走好了,执行完了,当我执行完成之后,你来看看值替换了吗,听完了没,听到了吗,不就是在这个步骤里面。

完成了这些替换值的工作吗。

就这意思,所以你要把这搞明白了,把这搞明白了,明白意思吧,好吧,来这块能听懂,同学给老师扣个一,能听懂吗,好了完成之后来再问一个问题,再问个问题啊,我们现在我们刚刚讲了XML文件的方式。

我问一下XML和注解,XML和注解谁先有谁后,有的是先有的注解,还是先有XML文件,插入文件吧,比如说我现在插入文件这样一个配置方式,我先有了XML文件,配件方式方式之后,我一定要写出一个标准的。

咳咳咳,是解析流程对吧,咳咳咳,这没毛病吧,就是我在有刚开始有插盘文件吗,有插盘文件之后,我要有个标准解析流程好,后面我有了注解,我问一下,当我有了注解之后,我是把原来的这些标准的解析流程都干掉。

按说我要在这个基础上做扩展,扩展啊,肯定是一个扩展点,对不对,在原有流程基础上,原有流程基础之上做扩展,那这个问题来了,我们之前写过什么叫at controller对吧。

At component scan,At import,有这样一堆注解,我问一下,包括我们的at bean1对这样的注解,这些注解都是干嘛的,注解是干嘛的,是不是用来生成我们具体的。

或者说用来创建我们具体的bean对象吧,是不是意思好吧,那在请创建并对象之前,是不是先要有BD,那你告诉我BD在哪在哪,是不是在这个bean factory里面,对不对。

如果在bean factory里面的话,我现在想对他进行扩展扩展吗。

可以怎么做,一样你找到我们刚刚说的叫bean factory post processor,这接口说它的一个实现子类叫什么叫这玩意儿。

不知道有没有见过叫configuration class post processor,在这里面会有一个方法来处理这块,就这个方法好,这个方法里面你可以往里面点点开它,然后往下走。

点了我们的pass好吧,找pass之后找到我们的pass找他,然后你往这看,还在下面这个东西,你看那有什么东西,稍微判断一下你当前注解有没有实现这个类,如果有时间这个东西的话。

OK好我就把它声明成一个具体的注解对吧,再往下走是什么意思,process处理任何at property source这个注解的处理,往下走,要处理任何component scan注解的处理对吧。

往下走处理任何at import注解的处理对吧,往下走处理任何at import resource注解的处理,再往下走,at bean注解的处理,我是不是可以在这个环境里面完成这件事,能听懂吗。

这不也是扩展点,就因为我现在预留出来了很多具体的扩展点,所以在后续的时候我想增强某些功能的时候。

我可以按照我的需要去随意扩展,这玩意儿就是这个东西的核心所在,你小白啊,如果你对这个源码没看过,同学你不需要听懂,你把我刚刚说的东西,什么扩展这两个事给我记清楚就完事了,明白意思了吗,能听懂吧好吧。

所以他要经过这样一系列的一个处理过程,当这样的一系列处理过程处理完成之后,好往下走,诶诶诶诶诶诶画不过来了,一条线过来好吧,等到这步处理完了好了,我现在获取什么叫完整,是BD对象,明白了吗,完成B对象。

有了这个完整的BD对象之后,紧跟着我就可以去创建我们的对象了,这个时候这个创建流程它应该是一个实现,也就是说从这块开始才开始,涉及到我们具体对象的一个创建,明白意思了,来到这儿,能听懂的同学在这扣个一。

能听懂吗,这这这我看这些东西都是从官网里面看的,或者自己研究对象里面看的,优化了,毕竟是啥了,不就是bean definition吗,我把这个搞清楚了好了,大家搞完之后,那下一步很简单,该干嘛了。

来创建对象,使用对象,销毁对象对吧。

系列 5:P32:32、详解spring的bean的生命周期 - 马士兵学堂 - BV1E34y1w773

呃说这三个步骤啊,说这三个步骤我觉得其实有点有点少,正常情况下,我们其实应该里面包含一些其他步骤的,这个创建对象,其实可以分为两个环节的,哪两个环节的,一个叫实例化,还有个东西叫什么呢,叫初始化。

我是希望大家把这两个步骤给分开的,一个叫实例化,一个叫初始化,比如说先有的我们的实例化,然后再给我们的初始化,初始化完了之后,紧跟着才是对象,使用才是相互对象,所以当你把这块一起框起来的时候。

这是个什么东西,这是我们面试中经常面试被问到的一个问题,不就是bean的生命周期吗,就是bean的生命周期,所以你就需要把这个bean的生命周期,好好理解一下的bean的生命周期,能不能搞清楚了好吧。

那我这我在讲这个bean的生命周期之前好吧,先说明一件事,什么叫实例化,什么叫初始化呀,我需要把这两个东西给大家解释清楚啊,初始化实例化有什么区别,注意啊,实例化指示,在内存中要开辟空间好吧。

那初始化呢最容易理解的是什么叫属性赋值,属性赋值,明白了,这是大家正常的理解,你也可以这样的方式理解,只不过在spring里面,它提供的初始化的环节会更多,或者在初始化里面做的东西会更多一点。

这东西我会放那一会给大家详细去进行描述,这打开的东西哇,所以这个图我希望大家能够理解到了,把这东西好好的搞清楚好吧,来刚刚讲的这些东西,能理解或者能听懂的同学扣个一吧,好不好啊,不是说创建变量。

要创建对象,在堆里面申请空间,是这意思,OK接下来我们来解释一个问题吧。

就是我们刚刚说的叫bean的生命周期啊,那bean的生命周期到底怎么去回答呀,这些并保存在什么地方,保存在我们的Mac里面去,在我们对象创建完成之后啊,有这样一个东西,一开始。

哎default b这东西就这样一个对象。

在这个对象里面呢,它里面包含了几个Mac结构,往下找啊,你找一下看吧,这三个东西这三个东西就是什么,就在这往上翻,是啥东西,这三个东西里面就用来干嘛,放我们具体的并对上了,这东西就是我们的一级缓存对吧。

这是我们的三级缓存对吧,这是我们的二级缓存,这东西明天我会详细讲的,别着急别着急好吧,但你记住容器里面是有一堆的map结构的,map结构里面放的是什么,放的是我们具体的一个对象啊,先不管它。

OK我们先来把这个B的生命周期啊,啊生命周期好好去理解一下,到底什么叫生命周期是怎么理解东西啊,我相信啊很多同学之前都背过吧,啊不用截图好吧,这图我分享不用截图,没没必要截图好吧,你们就好好听课。

我保证我这节课讲的东西你能消化一下,没必要去记笔记,我这个图会分享出去的,好不好好听课,到这之后来,我们接着往下讲讲生命周期,我问一下生命周期你们是怎么背的呀。

我相信很多同学肯定会搜索bin的生命周期对吧,出来一堆帖子,非常详细,告诉你,啪一堆好了,我背一下啊,背完之后面试去说对吧,当然有很多同学比较聪明对吧,图片看下图片,有一张图应该用的比较多的。

就是这张图啊,一共有13个步骤对吧,大家把这13个步骤给记住了,我问一下这13个步骤,你记住了就真的能理解吗,这里面我就问一个问题,同学们,我就问一个问题,谁能给我详细的解释一下,这玩意是干啥的。

要检查AVA相关接口并设置相关依赖,就这一个步骤,先给我解释一下,理解不了是吧,小琴说对了哈,小心说是对的,除了小钱,其他都不理解好吧,我们来详细画一下这个流程好吧,流程再次重申一件事,同学们记住了。

bean的生命周期不需要背,听懂了吗,bean的生命周期不需要背,你就按照正常的一个线性思维,去理解它就可以了好吧,怎么理解很简单,第一个步骤,我们叫什么叫实例化,刚刚我已经解释过了,什么叫实例化。

实例化干嘛了,是要干嘛呢,就在堆空间中,申请内存,当你申请完内存之后,我问一下那个对象的属性值是什么值啊,对象的属性值是什么,零现在还说零,现在说零不合适吧,默认值吧,默认值好吧,你数据类型不一样。

肯定是默认值嘛,对不对,然后呢,当你实例化完成之后,紧跟着第二个思维方式,你肯定就想着老师,我实例化完成之后,紧跟着下一个步骤,我一定要开始进行,什么叫初始化,对吧,那初始化的时候。

很多同学想到第一件是干嘛,不用猜吧,肯定是要设置属性吧,你肯定要说是属性,对不对,那这块在描述的时候,你要怎么去描述这东西啊,你不要大人就说实际话,你说实际话是不对的或者不严谨的,你该怎么去说。

你要说变生命周期,从对象的创建开始,第一步我们称之为叫实例化,实例化是通过哪开始的呢,通过一个非常重要的方法,那个方法名字叫什么叫create有being,然后instance好吧,通过这个方法。

可以完成我们具体的实例化的操作啊,那这里面怎么完成的呢,这里面实现的核心逻辑是谁,是我们的反射,对吧,这个时候可以把你的反射技巧带一下吗,什么反射技巧,第一步我要获取到对应的class对象。

第二步我获取到我们的构造器,第三步我要开始new instance了,来创建对象,我问一下这个反射代码会吗,反正不会的,扣二反正会吗,会吧,看下来简单写一下好吧,比如说我现在想创建一个对象,我怎么写。

怎么写反课呀,很简单,跪求百度,简单写一下吧,好吧,简单写一下,第一步获取class对象有三种方式,第一种叫class for name,对吧,你们在刚接触数据库的时候,下载驱动的时候都是这么干的。

写一个字符串,就把它写一个class,class等于第一种方式,第二种方式,The class,等于什么东西的类名点,Class,没有第三个pl,class等于对象名点get class,这是第二步。

第二步叫获取构造器怎么做,container c t o r等于class点get ecli,对不对啊,第三步叫创建,对象,然后object obj等于CTOR点。

new means hans都准备好了吗,就是讲代码啊,谁如果反射不会的话,下去之后一定要看,好好看一下呃,反射这东西是基本功,我们叫童子功,这东西如果你都不会的话,我觉得你的基础知识。

或者是你的技术储备是有问题的,是有问题的啊,那为什么这么写,很简单,因为原文里面就是这么干的,我刚给大家说了,你如果看的话,可以找到这个方法,我们来看一下。

做一下the create in instance。

是这样方法,那里面第一步我先获取到我的class对象,获取到之后呢,往下翻翻,下面中间都是判断逻辑,判断逻辑无所谓,这个东西叫实例化,点开之后有一个实例化策略,选择实例化特别精确,进来之后。

第一个步骤叫class,class等于BD点,get in class获取到我们的class类对象,获取完成之后,第二步叫class表,Get declared constructor。

获取到我们的构造器,当我有了具体的构造器之后,紧跟着通过been utils来进行实例化,怎么实例化的叫CTOR点,new instance啊,它就完成了我们的反射,刚刚有人提到这事啊。

说老师反射不是效率低吗,那为什么那个然后用反射呢,注意了,反射效率低,它是有数量级的控制的,你在10万加对象创建的时候,有一口气创建10万加对象的时候,才有可能效率低,就我们创业这零零星。

这对这对象效率还是很高的啊,为啥要用being in tibeuti是什么,是spring里面提供的一个封装类,网上提供封装类,方便我们进行相关的一些病的处理工作。

你在公司里面是不是经常封装一些工具类呀。

这是一样的意思,在spring里面他还帮我们提供了一个工具类,方便我们进行使用,就是这个反射,那这能听懂同学有点扣一,反正不方便,debug挺方便的,没啥不方便的,你不熟熟了就方便了,好好了。

这第一个步骤,所以当这个步骤执行完成之后,我们第二步骤干嘛了,该叫设置属性,设置属性呢同样,也会包含一个非常重要的方法,发的名字叫什么,叫pull b,有这样的方法,这个方法完成什么事情。

就你们刚刚说的,要给属性赋值,怎么赋值调用,set方法赋值里面就是这么干的,叫populate d,明白意思吧,啊populate b,这没问题吧,这是我们正常的一个线性思维吧,紧跟着第一步,先实例化。

实际完成之后,我们该进行设置属性了,来这块能理解同学给老师扣一,这样能理解吧,我觉得这个应该方便大家理解啊,当这个步骤完了之后,紧跟着下一步该干嘛了,如果你去看那张图的话,背那张图的话。

他告诉你叫什么叫检查,相关依赖并设置对应的一些属性,很多同学对于这东西是模棱两可的,或者说认知不清楚的,那什么叫检查where并设置相关依赖呢,其实非常简单啊,先先来看一下这个接口吧。

play接口叫什么叫aware这个接口,这是干嘛的,这个单词怎么翻译啊,谁能告诉我单词,感知对不对,联想到意识到通知对吧。

是这个意思吧,你如果看源码的话,你可以打开这个接口看一下。

这结果很好玩,他跟我们那个那个呃SERIALIZABLE接口一样,里面什么都没有,它是一个空的接口实现,那为什么要包含这个玩意呢,或者这么个东西,它到底有什么样的意义和价值呢,举个例子你就听明白了。

好吧,来举个例子有啥意思呢,写在哪了,这块我写一个代码在里面new一个class,比如dog,好吧,我定义好dog类之后,我里面一定会干嘛,叫private int id,没问题吧。

private string name我一定可以定义这样一些属性值,是不是意思,当定好属性值之后,我必然要干嘛呢,写上它对应的set和get方法,然后呢,我在设置属性的时候。

我可以调用这些对应的set方法来设置属性值,没问题吧,等一下我调用,公共的set方法完成属性值的设置工作对吧,这能理解吧,一般都这么干好吧,但是有一个问题,同学们除了我们这样的一些自定义的属性之外。

还可能包含一些额外的属性,什么属性呢。

很简单,也就是说在整个容器里面对象好吧,如果按照使用者来分,可以分为几类,就是说啊按照使用来分,可以分为几类,两类吧,第一类叫什么叫自定义属性,比如说我们写的什么person啦,dog啦,看见啦。

这东西的定义属性就之外,还有个东西叫什么,也叫容器属性,什么叫容器属性的自定义对象,就自定义属性对象,还有什么叫容器对象,什么叫容器对象,就在容器里面使用的时候,或者容器在调用的时候需要用到对象。

这边有哪些啊,比如说很重要的,我们说的叫bean factory,再比如说叫application context对吧,再比如说VIRONMENT,对吧,这就是说RESULLER。

这些对象是你是我们自己创建的吗,不是吧,都是容器,在整个运行过程中。

他们自己需要的对象是容器的吧,哇那假设我们自定义的对象里面,他如果包含了这样的属性怎么办,Create b factory,可以这么写吧,Private the application contest。

你不要问老师,我我对象里面不需要包含哪些属性,假设就需要吗啊假设结果呢怎么办,他们两个都是私有的属性,就意味着一件事情,我必须要通过公有的set和get方法,来把它给设置进去,对这里面会有一个问题。

什么问题,这就是谁在什么时候调用此set方法,为什么需要举个例子啊,举个例子,你这有道对不对,看完了你这有道到对象到对象交给容器,加入容器之后,我外面我写了一个测试类在里面可以怎么写呢,可以这么写。

这个叫context,第2get b dog,The class,当我设置好到对象之后,跟对象之后,我突然需要把dog对象设置到某一个对象里面去,怎么办,或者说我需要对。

只需要获取容器的其他对象来进行操作,怎么办,在多个对象中,在B对象中,啥意思呢,我dog里面我写了一个方法,写下,还有一个,Do do,你再写一个并开口,在这里面我需要干一件事,干什么事呢。

叫bean factory,点get be,写一个,我这不传参数了,这么干,我这里面需要用这个东西,我就需要用这些bat对象怎么办,你能保证你的容器里面严格不需要这玩意吗,你能保证吗,只有这样一个代码。

我这个地方怎么办,怎么负责人,你告诉我,你是不是需要把它设置成一个属性,你把它设置成一个属性之后,我是不是才能进行具体调用了,是不是,这意思能听懂吗,啊能听懂不,为啥要设置成私有属性。

大哥咱们学面向对象三大特征的时候,属性不都是私有的吗,看看为啥要设置成私有属性,这就封装吗,所以这里面我就必须要干嘛,把这个对象或者把这个属性给它赋值附上,如果我想赋值附上的话,我怎么赋值。

我一定要调用我们的SAMA,你XMB,你的赋值可以按你们说的来里面写配对象,class报告,我写这样的东西,我里面解属性了,property name等于deploy,你告诉我这写谁。

你告诉我这写什么东西,我写啥,你要想reform,你必须要干嘛,是不是有一个对象在这,你没对象,你写啥,你写你写不了,你喜欢那玩意儿就没法这么干,完了怎么办,所以我要把对象给它设置进去。

设置进去之后就是一件事,我是需要调用我们的set方法,来给大家进行处理的,这有一个set factory,下面有一个set application contest,在这里面就有个问题。

就是谁在什么时候变回复方法,谁在什么时候掉,第一个问题谁要告诉我,谁来教,是我们自己去掉吗,不是吧,肯定是容器,第二个问题在什么时候掉,啊什么时候初始化,你说一个初始化是不是太太太粗了。

别忘了这有个set factory in factory,还有个set up in contest,我如果在后面再加一个environment,我这可能还要再加一个,就set in warm,什么叫。

所以你很难判断,因此怎么办,很简单,能否,设置一个统一的接口来作为标识啊,当实现此接口,到时候来统一的设置这些属性操作,什么意思,当你打开aware接口之后。

你可以搜一个接口叫B。

它里面有一个方法叫什么叫set bean factory,当您打开这个叫application context aware的时候。

还有个方法叫什么叫set of lication contest,当你需要的时候,上一个environment aware接口叫set environment。

看到了吧,所以我可以做什么事情,我只需要在当前这个类上面加上一个东西,就行了,加什么叫be briaware对吧,application context aware对吧,Environment。

我里面是不是已经包含了这些四联通网了,那么我在进行这些属性的设置的时候,怎么判断,我只需要判断一下这个bean对象,instance of aware不就完了吗,怎么做一个都能判断B不括号。

ban instance of aware对吧,里面可以做什么设置,If,变instance叫BETHEORC,你还可以怎么调ban点,Set bean factory,我不可以进设置了。

能听懂这意思吗,我是不是可以这样逻辑判断。

所以在这里面他也是一样的,在这个方法在里面的调用aware相关接口里面,都是说做什么事情,它所对应的方法也非常简单,就刚刚说的叫invoke,Uh aware methods,这东西有这玩意。

你可以打开。

我要看看。

看了吗,Ban instance of aware,Ban instance of benim,Aware beset,Benin bin carloader。

Aware beset beculoader,看到了吗,你能不能做这样设置工作啊,能同学们能吗,听懂了没,听懂了没,这没问题吧。

所以你再反过头来想一下,什么叫调用aware相关接口并设置相关依赖,这句话怎么去理解,啊什么理解,这部是不是也是设置,属性啊,上面设置什么属性叫自定义属性,下面呢找容器对象属性,听懂了吗。

所以他们两个包含在一块的时候,都属于什么操作,加上这个底,这个底,他俩统一叫做设置属性,懂了吗,啊明白意思吗,你现在你你想要什么,叫检查偶尔相关接口并依赖,有这玩意吗,就调用这些方法吗,完成这个工作吗。

来听懂的扣一,明白了吧好吧,所以把这东西理解清楚了,理解清楚了,当这块搞明白之后,紧跟着下面再来注意了,现在实例化堆里面已经有内存了,点歌的我的属性设置完成了,属性设置完了之后。

紧跟着郭凤龙还在问说奥威尔接口做什么用的,我讲了半天,我在讲啥,哪个在哪个设置自定义属性在前,服务器属性在后,好吧,明白了吗,所以当这个步骤做完之后,其实我这画一个大箭头,正常情况下。

在我们自己在创建对象的时候,你告诉我我自己创建对象的时候,是不是创建完之后就结束了,就这样还能划分一下,只要划分一下,很简单,当这个步骤,当上述方法调用完成之后,的对象能否直接拿过来并行使用,那么。

我告诉陈说了,要是自定义对象,这个时候还没在容器里面怎么办,你容器创建的时候已经把这些东西创建好了,明白了吗,他在前期的时候有很多对应的依赖,已经提前把对象创建好了,不会出现你说的那种情况。

压根不会出现,你详细看源码就知道了,那些对象提前都准备好啊,这对象能不能直接使用,可以吧,是可以的,但这个时候你要思考一件事,什么事,还是我们之前说的什么,他是一个框架呀,我不可能拿过来就直接使用了呀。

对不对,我还干嘛,比如老师是不是该纳入容器管理了,没到这块,他什么操作,判断是否需要对bean对象进行什么扩展,又是扩展这个点,所以当这个步骤我结束完了之后,紧跟着会做什么工作,做一件事叫执行铺。

叫前置处理方法好吧,有前置意味着一定有后置,叫执行后置处理方法,很多人很懵逼,老师什么叫前置,什么叫后置,这样东西到底怎么样去理解好吧,它与生俱来对应的,是我们的另外一个对象。

就是我在前面已经给大家做个普及的一个东西,什么叫b post processor。

这玩意儿如果你打开这个接口的话,你会看到看一下ban post的同色的。

但是里面两个方法,一个叫post process before insulation,后面还有一个post process after insulation,好吧,所以这两个对应过来之后。

就是前置和后置的处理方法来,这能理解同学给老师扣一,我不需要做扩展,无所谓,我如果不需要做扩展,没关系,你跳过就可以了,如果你需要做扩展,你是不是在这里完成对吧,有什么用,并对象需要做什么扩展呀。

需要吗,我问一下,在spring里面有一个非常重要的东西,除了IOC还有个东西叫a OP吧,是的,Vip,我问你个问题啊,a OP的底层实现原理是啥,AOP的底层实现原理是啥,动态代理。

动态代理的两种实现方式是什么,第一个叫DK,第二个叫CDDD,没毛病吧,所以假设我现在这个对象,我就需要被创建动态的对象,怎么办,是不是意味着我要在中间某个步骤里面去生成,我们代理对象,我不可能不生成。

我是一定要生成的,那如果我想生成的话怎么办,我是不是一个接口,所以我要去找到这个接口。

这个接口里面一样,你点开之后会发现有一堆的实现子类,一堆装着一个,找一个东西找他叫abstract auto propose creator是吧,你看这个东西吧,当你看到这个东西之后。

你找谁找它的前置和后置处理方法,我们先看前置,等一下叫before insulation,你告诉我这个前置处理方法里面有做,有做任何工作吗,有做任何工作吗,没有吧,有作品是录播吗,对是录播,没有吧。

前置如果没有的话,那就找谁找后置嘛,对不对,点开后置,后置里面是有处理逻辑的,那好了,我们来看一下它的处理逻辑怎么看啊,找他的方法吗,有一个方法叫什么叫mapper,if necessary对吧。

来点F4进去,点完之后往下拉拉拉拉拉,拉到这行来告诉我这个方法叫什么,叫啥啊,叫什么创建代理,对不对,按代理,然后再点进去,回到最后一行叫purpose fruary,点get propose。

我要获取我们代理工厂,我再点进去,是不是获取我们AOP代理对象,然后来获取代理DMC,进去进来之后发现他是接口里面的某一个时间,此类,那么这个时候你再点开它的实现,此类咱们你们看到了什么。

cg live a OP pose和jdk dynamic a OP prose,所以很多人都问我,老师动态代理或者a OP的入口在什么地方,这不是入口吗,是不是意思。

是不是我们刚刚看到的两种代理的方式,明白意思了吗,就从而进来的吗。

所以我可以干嘛,是在我们的后置方法里面,完成我们代理对象的创建,Raise,这不就是我们对应的一个扩展点吗,明白这意思了吧,所以你要把这个东西给理解了,刚才问我说,老师为什么AP要存在两种代理。

那你让我咋解释,谁能解释一下为什么a OP要存在两种代理啊,啊为啥他就是两种方式嘛,为啥为啥他就提供了两种实现的方式嘛,对不对,好吧,你要想用的话,你只能用这两种方式来进行实现嘛,不就这意思吗,好吧。

所以把东西搞清楚了,这中间是这块处理的一个逻辑,也就是说前置处理方法和后置处理方法都有,你可以来进行自己的一个实现,选择在前置处理方法里面进行扩展,也可以选择在后置处理方法里面进行扩展,你随意来挑。

看你心情,你开心就好,这么简单,明明白意思吧好吧,当你这儿搞明白了之后,所以扩展点就结束了。

但是你注意了这两个扩展点中间那个接口,它的名字叫什么。

叫post process before,后面有个单词叫insulation,是什么意思啊,倒过来叫什么叫初始化,可能会懵逼的,老师怎么又一个初始化呀,我们最外层的这块不就是初始化吗,这是又一个初始化。

这个初始化是什么,它表示的叫什么叫调用初始化方法,什么叫调用初始化方法呢,也很好理解,同学们,等我把这圈画完,两条线好,什么意思呢,我们在配置某一个具体的bean对象的时候。

你是可以在bean对象里面加一个操作属性的,什么属性随便点开一个,这可以加一个叫init method,就是我们说的初始化方法,当然这个初始化方法一般是不用的,一般是不用的好吧,所以我们也没人计较这事。

它对应过来的一个方法,处理逻辑叫什么,我写到这边吧,叫invoke delete method,配置最大名的就这玩意儿好吧,其实这个方法其实并不是特别重要,并不是特别重要,关键点是什么。

在当下这个方法里面,它也包含了一个相对比比较重要的处理逻辑,什么逻辑呢,它会判断,当前的B是否实现了一个东西,叫是否实现了intryon be这个接口,什么叫你来定啊,这玩意怎么理解呢。

在这里面如果你实现了它,那里面会调用,一个方法,你们很多人应该见过叫up,Property debuff,你实现这个接口,OK我才能调这个方法,如果不实现,我就不调了,明白意思了吗。

这句话能不能理解这俩中间这块的处理逻辑,我调一下,哎哎好了吧,明白意思吗,很多同学在公司里面应该是用到,用到过这个方法的,明白吗,所以这个it method并不重要,重要的是这里面这个东西。

你要把这东西给理解了,懂我意思了吧,好所以这就是这块的一个除油剂,当你这些东西我都做完了之后,就像你们刚刚说的,在干嘛呢,要把对象交给容器来管理对吧,当我交给容器来管理之后。

紧跟着下一步是不是一个东西叫对象啊,使用吧,我对象使用完了之后在干嘛。

是不是要对象销毁啊,明白吗,怎么交给对象,我告诉你怎么叫对象好吧,当你创建完完整的对象之后好吧,你可以看到一个方法叫do create bean。

方法在多奎的be里面好吧,就是我们刚刚说的一些完整的处理逻辑,比如说这块,你说艾滋病第一步要调用aware methods,第二步执行前置处理方法,第三步执行我们的net method。

第四步执行后置处理方法,当这些方法我都执行完成之后,我往回传龙眼上面这东西处理完了,我可以把对象返回回去了,一直返回把这注册一个要销毁对象。

把对象暴露出去,当暴露出去之后,你可以找一个东西叫get。

Wink,这一方法哎不是这个。

叫get singleton,诶是要get smoon吗,找一下,那不叫干干的新闻。

是这个方法啊,那里面可以传一个这个东西,在这个方法里面有一个这个操作逻辑,叫他找at singleton,在这个ADSLETON里面看,这叫this single object put。

把暴露的对象给他传回去,把它放到一级缓存里面去,然后你把它放到一级缓存里面去了好了,容器就帮我们给管理起来了,明白意思了吗,就这块处理逻辑好吧。

所以你要把这东西理清楚了,就是我们说的整个bean的生命周期。

这时候有人会问老师,这个对象销毁你不讲吗,我一般不怎么样销毁,为什么不讲对象销毁,你们有自己的销毁过对象吗,同学们,你们有销毁过对象吗,我什么时候会触发这个效果,对象不是JCJC是垃圾回收容器。

里面是可以有一个关闭操作的,也就是说我们定义好一个具体的容器之后,比如说我们写的application contest,当你定义好它之后,在这里面你可以写一个context,点close方法。

当你调用close方法之后,你才会受到销毁,但是你告诉我你们谁写过close方法,每次都是直接点这东西结束吧,谁写过没写过,所以面试没问,没人问销毁,你感兴趣,你就看看,不给你就算了,无所谓啊。

面试我们到目前为止没人遇到过问销毁的,所以你们也不需要在这上面浪费时间好吧,把销毁这个步骤记住就行了,所以这就是我们说的这个bean的生命周期,难理解吗,那同学们都能好不好理解,我就不难吗。

我还说这句话,这东西需要背吗,我觉得不需要背,我觉得不需要背,你就跟着去听好吧,理解这东西好吧,按照流程去捋这样的一个思路,捋这样的一个逻辑,我都说了,不用截图,我发给你们这个图,这图我给你们。

二维码有好吧,加过咱们咨询老师的同学是扫描二维码没加,没加过同学扫二维码加我指,他要好吧,把这个给大家,把这图给大家没问题啊,刚才说老师这个宝贝说老师太粗了,本命太脆了吗,我说了这个干嘛。

主要是帮你梳理你整个的逻辑线,我不是说我要一行一行带着你们去debug,如果一行一行带着你们debug,我告诉你几个词搞不定,没几个词根本搞不定,明白意思吧,另外依赖那里是不是代理会提前,是的。

如果你出现了循环依赖,那么代理对象的创建是有可能会提前的,这是明天我们要讲的东西,我告诉大家,你不需要去了解这些细节,如果你面试的时候能够按照我这样的方式,把这些东西都给面试官说清楚,面试官不会再问了。

我之前专门讲过我们面试突击班的源码,就spring源码,我如何让你在短期之内考虑这个东西,你不需要去看源码,K2没有意义,也没那个时间,就这个源码课,swim我大概讲了80个小时,课分VIP课。

我讲了80个小时,你马上要面试了,你有80个小时先直接去看这东西吗,纯视频八个小时,你自己消化消化160小时,不过分吧,对不对,所以你不可能,所以会告诉大家怎么样,你要掌握的是什么。

是一整个就是这个表述的方式,你要怎么去回答这个问题,让面试官感觉OK够了,我不需要再问了,明白意思吗,所以我说我之前也讲过这东西吗,我给他找一下,我也专门讲过这种面试,同学们当时上课的时候。

大家手敲我说答题技巧看好了好吧,哪个区点12345分开描述啊,避重就轻,没有重点好吧,有问题能站稳,面试多长时间,问的越多,可能漏馅越多,所以尽量拖时间,怎么去理解这东西,怎么解释好吧。

端着怎么去描述好吧,传一下LOK的比分实现,并且生命周期我要怎么去描述好吧,怎么解决循环依赖的问题,我要说什么东西,你把这个搞定,就按照我说的,里面会带很多的类接口方法的名字,你把这些名字记记住了。

然后面试的时候去跟面试官去说这东西,面试官感觉到哦,原来你学过或原来你看过这个源码,明白意思吗,内部反着给VIP的是吧,好吧,我说了这个图给你们,但是我这些带中文注释的这个源码我是不发的,为什么不发。

解释一下,因为这是给VIP在讲VIP课的时候好吧,分享出来的东西,我为了讲VIP课,我辛辛苦苦写的,如果免费给到大家,对VIP不太公平,所以非常抱歉好吧,所以买东西我希望大家能够记住了。

OK这图我可以给到大家,这个没问题,你把整体思路捋出来,捋出来之后按照你整体的东西,然后你整体逻辑自己下去之后。

好好去干一下,好好去跟一下,好好去debug一下啊,这事比什么都重要。

系列 5:P33:33、BeanFactory和FactoryBean的区别 - 马士兵学堂 - BV1E34y1w773

好了,来回到我们这节课上面,第一个变成生命周期,能说清楚了吧,对不对,第二个重要的扩展点,第一个刚刚说的,你在执行post process里面post,呃这叫什么来着,Post in factory。

post processor的时候,你可以有一个扩展点,那个模板方法,还有那个on reflesh对吧,可以有模板方法的扩展点,除此之外,你的BBPP和你的BF p p,是不是都是我们的扩展点对吧。

这就是我说的扩展点,你能把这三个东西给面试官说出来足够使,因为一般人根本理解不到这个程度好吧,第三个,bean factory和application content的区别不用说了吧。

一个是它的子类实现而已好吧,第五个,看来你对此的理解,看那个问题的时候,就按照我上课说的东西,这东西来来来来说就可以了好吧,第四个问题刚刚没说叫bean factory和factory bean的区别。

有人为什么绕过这个问题吗,就been factory和factory bean的区别,有人问过没,问个扣一,这俩有什么区别啊,其实区别点啊非常非常简单来说一下,In factory。

还有factory bean,首先啊两个东西,两个东西他们都是用来创建对象的,明白吧,都是看对象的,都这样的功能,但是我们在使用并battle这种模式,来判断对象的时候,它类似于什么呀。

叫必须遵循完整的bean的生命周期,创建对象是不是意思,我问一下这个过程麻烦吗,复杂吗,你们觉得,不复杂,你debug一下原版就试试了,你第八个一下原版就知道了,很复杂,我刚刚在你看的时候。

有很多逻辑判断是跳过去的,没带你们看,如果你加上那些逻辑判断的话,它是非常普通的好,所以我把它称之为什么呢,很简单,叫流水线式的创建对象,流水线式创建对象,然后你点一下点个门,像没点烟好吧。

第二个factor是什么意思,它更多是什么,也是创建对象,但是没有标准的流程啊,它更多类似于什么东西叫私人定制,什么叫私人定制呢,其实很简单,比如说这里面他这个接口里面会包含三个方法。

第一个方法叫什么呢,叫is singleton,什么样的sequence很简单吧,判断是否是单例,这是第一个说到这,还有第二个方法叫get object type,这返回对象的类型还有第三个。

懂了叫get object,什么叫返回对象啊,还有这三个东西,那有这三个有什么用处呢,很简单,比如说我刚报告打开我们的类,我如果在这上面也实现了这个接口,实现它里面的方法,这两个还有一个叫意思。

第一个如果是单列的话,返回true对吧,get btt tab可以返回dog点class对吧,第一个这个get到变成你可以怎么办啊,你怎么办,很简单,第一步,dog dog等于又一个dog。

可以不自己new吧,还有什么还有啥该怎么做,dog点class点get deconstrutter,New instance,我是不是也可以返回一个对象,对不对,第三种我可以使用什么动态,代理嘛对吧。

enhor enhancer等于new一个enhancer对象,然后在enhance里面我可以设置一些set什么东西,设置一些东西,做完这些东西东西之后,然后呢来进行进行创建,是不是也可以。

然后最终我返回一个报对象,是不是也可以,你是不是可以按照你自己的一个方式来进行,对象的一个创建,能明白意思吗,同学们这意思。

所以这是他们两个之间的区别,来这块能听懂,同学给老师扣一,能听懂吗,所以把这个东西啊大家搞清楚啊,这是这是我要讲的一些点,对这几个问题,我希望你们在面试中,如果在面试被问到了啊,能够把这些东西啊搞清楚。

不要因为这些问题再被卡住,很难受啊。

同样的,刚刚我也带你们看了一下源码,一直在讲给大家捋思路。

捋的思路。

系列 5:P34:34、源码学习方法论 - 马士兵学堂 - BV1E34y1w773

我问一下,听过我的讲解,你能不能总结出来,首先第一点啊,现在还有多少同学觉得原版难的,给老师扣一,他多少觉得原版难,不能的扣二好吧,按键怎么样,下面还不扣一而那句话,大家在看源码的时候,为什么觉得难。

是因为大家没入门或者没找到合适的呃方法,比较合适的方法掌握,好好学习技巧的学习效率会呈指数级增长好吧,所以呢下面我给大家分享的东西要学习,别晚上饭盒,你们不要想着你们不要想着说老师。

你们有没有什么内部资料,我看完这些内部资料之后,我就能够就是把这些东西都理解的倍儿清楚,这不可能所有的技术啊,你记住,如果你觉得难的技术,它一定是所有人都觉得难,如果多人都觉得难的话。

他是一定要需要你去耗费时间和精力进去,然后才能达到好的效果,如果你不耗费时间和精力进去,我告诉你根本学不会这玩意儿啊,它只能治标不治本,所以这里面有一些方法的东西,我需要给大家说一下,明白了吗。

聪明人都是下笨功夫,这句话我非常认可,就不止一个人觉得难都难,但是你要反思一件事,就是越难的东西怎么样越值钱,把这事记清楚哪去好吧,学学派有哪些技巧,我不建议直接看书啊,看书会误导你的思路好吧。

看书会误导你的思路,一方有什么方法呀,第一个我要强调的不要忽略源码中的注释,这点很重要,很多同学啊,你们不善于看注释,源码里面,并不是说我每一行代码我都给你写注释了,并不是这样。

而在关键性的地方我才会给你写注释,所以他写注释的地方,一定是他觉得这个东西可能会比较难理解,明白吗,所以你是必须要去看那些注释的,不要看了之后装没看着,同学说老师我英文能力比较差。

我看不懂注解怎么办,哎呀还有人问这样的问题,毒死人,你说这种东西有什么看不懂的,你告诉我能不能这样啊,看到东西了吗,你能不能加一个翻译啊,大哥,怎么加翻译。

可以的,有很多插件,你翻译一下,对不对,这是第一点,第二点还有什么,叫先物理脉络,好再去,抠细节,很多同学啊为什么看源码没有看进去,或者说为什么没有坚持下来,原因在于什么地方呢,原因在于很多同学手欠。

这个不是骂人的话,手欠什么叫手欠呢,就你在黑暗马上的时候看到一个方法,总想点进去瞅一眼,看到一个方法,点进去瞅一眼,看到一个方点去瞅一眼,等你一直往里边点,点,到最后之后懵逼了,哎我为什么要进来。

这个我干嘛来着,一脸懵,回过头来的时候也不知道自己从哪进来的对吧,进去看的时候也没看明白是个啥,就这样稀里糊涂的这标点是吧,现在说明好对应的脉络脉络,搞明白之后再去看里面的细节。

就比如说我刚刚画了一张图,我今天我就看一个东西,就看XML文件的解析,明天就看具体的解析,后天就看并put processor处理是吧,大后天就看实例化,大后天就看初始化,你一步步分开来看好吧。

先把脉络给大家一定要理清楚,懂我意思吧,不是这个事,第三点发生什么,有见名之意,原版中的LCL好吧,方法它的名字起的还是相对比较规范的,所以你有时候看到那些方法名字之后。

你就足以猜测到它到底要表达什么意思,或者说这个到底干什么事,那这个时候你就不需要再点到里面去看了,没有意义没有意义,明白意思啊,这第三点第四点,那什么东西叫大等猜测,小心验证,你们听我哔哔的夜晚上吗。

感觉啊老师你讲的好牛逼啊,老师你讲的挺好的,但这东西是一定是对的吗,源码又不是我写的,只是我自己的理解而已,明白了吗,只是我自己的理解而已啊,我理解的不一定对,只不过说能说的过去,或者说能自圆其说。

你们也是一样的,看到一个功能之后,你去想它这么设计的原因在什么地方,他这么写的原因在什么地方,为什么这么写,去猜,看完之后去看他的详细的逻辑处理过程,这么做到底是为了啥,搞清楚这些东西,明白意思吧好吧。

然后第五点,什么叫善于使用小插件,比如刚刚给大家说到翻译的translate对吧,比如说还有东西叫sequence,都可以用这些插件,你好好去看一下好吧,理解这些东西,然后第六点很重要一点就是坚持。

别的东西肯定是难,谁都知道难,我也知道难啊,你们所有听课的人都觉得这个东西难不难的话,你们就不会来听课了啊,难不怕,但是你要坚持下来,别跟我们之前讲课的时候举个例子,我说很多同学这个时候为了考四六级。

背了4年,又记住一个单词叫abandon,就放弃,啥东西都没记住,不要这样,你一天看一点点,一天看一点点,不要怎么每次都开始从头看,你每次从头看,每次什么都记不住,明白了吗好,所以一定要坚持走好。

搞明白这东西,你把这东西搞清楚了,那会的就是会的,哪怕你忘了,比整体的逻辑思路线是不会断的,而如果你不看这东西,我告诉大家,你以后可能会越来越难受,大家有同学问我说老师源码是什么样的知识,同学会问。

你觉得沈阳这些同学会问,就是你拿多少薪水,可能会问源码,你们觉得其实坦白说,原来的时候问源码的人其实并不是特别多,源码其实原来没那么多人问,真的没那么多人问,好吧,大概就是问一下IP的生命周期。

啪你一背背完之后,OK结束了啊,不用再问这东西了,但现在几乎你的薪水,如果想要到20K以上的话,基本上都会问到这东西,问东西原因是啥,你说你工作能用吗,同学们,我问一下,你工作能用吗。

有很多同学都问我老师,我学学法的原因是啥,是因为我工作要用吗,不是你工作中,我告诉你,就你们天天写一些CLOD业务逻辑代码。

系列 5:P35:35、循环依赖的基础知识铺垫 - 马士兵学堂 - BV1E34y1w773

首先先来解释一件事,什么叫循环依赖啊,你怎么理解啊,其实非常简单,当我们定义好一个对象之后对吧,比如说我定义了一个A对象,A对象里面可能会包含一个属性叫做B对吧,同样的我可以再定义一个B对象。

B对象里面有一个属性A,当他们之间相互引用的时候,就出现了我们说的循环依赖问题,那为什么会出现这个问题呢,其实也非常简单,问大家一个最基础的知识,在spring里面bean对象默认的是单例的还是圆形的。

默认是哪种形式啊,单例吧,如果你不做任何特殊设置的话,基本上都是单例的,什么叫单例,也就是说我这儿有一个容器,容器是什么,就我之前给大家说一个map结构,这放了一个map容器里面所有的对象,找对象好吧。

叫有且仅有一个,有且仅有一个,这叫单例好吧,一般情况下bean对象啊都是单例的,单例的话,这就会有一个问题,我现在有两个并对象需要放到容器里面去,如果我要想往容器里面放的话,就意味着一件事。

容器里面的这个对象必须要创建完成之后,我才能够把它给放进去,所以我不管是A也好还是B也好,我一定要优先网络创建一个对象,假如让我先创建A,那么意味着我可能在创建A的过程中,需要去设置我们的属性B对吧。

那我再检索一下有没有B属性,如果没有B属性的话,怎么办,我是不是要去创建B对象了,而创建B对象的时候,紧跟着话又会有一个属性A的设置,我要去看一下有没有属那个对象A,所以这样的情况下。

就造成了一个循环依赖的问题,想把循环依赖这些问题搞得倍儿清楚的话,朋友们一定记住了,需要大家对于整个bean的生命周期是有所了解的,也就是说生命周期并到身为NBD,生命周期是前置知识啊,叫前置知识。

你必须要会的东西,因为你会这东西之后,对你的理解会相对容易一点,今天我也会带着大家去比bug源码,带你看一下他详细的流程到底是什么样子的,以及他到底是如何去解决当前问题的哦。

当然我也知道咱们有很多同学啊,可能之前没有自己debug源码,没有也没关系,到时候我上课会一步一步带大家去进行操作,你到时候好好听就行了,在上课之前还是一样,先重复一件事,同学们记住了。

今天上课期间你不需要自己去做任何的笔记,我今天晚上画了图,下课之后会分享给大家,对上课的时候,你只需要做一件事情,全神贯注的去听我的讲解就OK了,不要去记笔记,跟着我的思路把它给贯穿下来,很重要。

好吧好了,既然提到我们的生命周期这件事情了,我先问一下,如果我们按照一种比较粗的力度来划分的话,生命周期可以分为几个步骤,记住啊,叫粗粒度来划分,可以分为几个步骤,昨天上午讲过的四个吧,哪四个。

第一个叫做实例化,这句话完成的工作非常简单,就是在堆里面申请开辟一块空间,这是第一个步骤,紧跟着第二个我们叫初始化,初始化完成的工作也比较简单,第一步可能是给对象的属性进行赋值嘛对吧。

然后呢我要进行某些额外的扩展工作对吧,调用一下我们对应的初始化方法,对不对,就不干就干这几件事,然后初始化完成之后好了,我可以进行使用了对吧,当我使用完毕之后,我可以进行销毁了,大概是这几个步骤啊。

大概是几个步骤,然后今天我们在讲循环依赖问题的时候,我们不是每一个步骤都聊,我们重点好,我们重点聊的是谁,主要是实例化和初始化这样的一个团结。

比如说我们在说对象创建的时候,就不聊对象的使用和对象销毁了,只说对象的实例化和初始化,因为你们在之前自己看帖子或者看书的时候,一定有人听说过,在spring里面到底是如何解决循环依赖问题的,谁能告诉我。

你们看我帖子怎么总结的,一般情况下会给你两个名词,一个名词叫做三级缓存对吧,第二个名词叫做提前暴露对象,但这个时候其实你应该有一个疑问,什么疑问,三级缓存指的是哪,三个缓存,提前暴露对象。

对外暴露的到底是什么,像这些东西面试中都会问的,像最近面试问的是什么,他不会说只问你说来你给我讲一下循环依赖,各位问你一个问题,很尴尬的问题,说为什么循环依赖必须要使用三级缓存,二次缓存行不行。

一级缓存行不行,为什么必须是三级,他会有这样的问题,所以今天听完课之后,我希望你能够把这个知识给详细的表达出来,面试的时候好吧,能游刃有余的把这个问题回答出来。

系列 5:P36:36、图解循环依赖 - 马士兵学堂 - BV1E34y1w773

好吧废话不要这么多,下面我们来模拟一下AB两个对象的创建过程,因为啊我现在有两个AB对象了,那我在创建之前就意味着一件事我怎么做呀,首先第一个步骤画一个图啊,看看这个图,第一个叫创建A对象,这没问题吧。

好吧,我问一下创建A对象的时候,要包含几个步骤和环节,第一个是什么,第一个是啥反射实例化吧,我们还是我刚才说了啊,我们说的时候只说这几个步骤,实例化也就是说对吧,实例化就是绿化A对象。

当我完成A对象的实例化操作之后,我的问题是这里面的B属性此时是等于什么值,B是什么值,默认值吧,等于空对吧,然后紧跟着第二个步骤要干嘛,是不是要给,A对象的B属性,变形赋值的,那么在进行赋值的时候。

大家应该知道容器里面的对象默认是单位的,也就是说有且仅有一个对象,这下面我会去判断一个东西,判断啥,判断容器中是否有B对象,那是否有的话,就意味着一定有一个事,下面会有两个路径,有或者没有吧好吧。

来往上写,如果没有,如果有有的话怎么办,如果有这个值,那OK我直接赋值即可吧,是不是直接完成赋值了,赋完值之后好了,把它给回去结束了对吧,那如果没有呢,嗯没有没有,它意味着下面我干嘛要创建B对象吧。

是不是意思,而创建B对象的时候,因为你要遵循完整的bean的生命周期,所以整体的流程和步骤是一模一样的,所以第一个步骤干嘛叫实例化B对象,当我把B对象实例化完成之后,紧跟着里面的A属性等于什么值。

空值吧,依然是默认值等于N,当N完了之后,紧跟着再进行一个事,叫做给B对象的A属性进行赋值,那赋值的时候,这上面一样必然要经过一个判断,判断一下你到底是判断一下,判断容器中是否有A对象。

那我既然要判断一样两个步骤,要不然有,要不然没有,如果没有嗯,先写有吧,叫直接赋值即可,然后这条线连过来,写一下,有这样的,如果没有,没有就这个步骤,这能理解吗,我刚刚画的这个步骤没问题吧。

所以在我刚刚画的这个步骤里面,你能不能看到一个非常简单且直接的闭环操作,这么长吗,小一点,看这个你看到了吗,这就是我们说的循环依赖吗,在整个整个执行过程里面,它形成了一个闭环嘛,是不是这意思,死循环吗。

那死循环其实就是我们要解决的这个,循环依赖的问题,这是为什么面试中经常问这个问题,好吧,那我们怎么样去解决这个问题啊,很多同学在遇到这样问题的时候,说老师完了形成闭环了,这个闭环我要怎么解开。

你记住所有的闭环不只是循环依赖,任何地方,你在遇到闭环的时候,你要想解开这个闭环思考的维度是什么,在哪个地方是最后一个步骤落成了闭环,我们刚刚画张图的时候,在这这个步骤是不是形成闭环。

假设这条路径如果没有的话,把它删掉,如果没有的话,还会有这个闭环吗,不存在了吧,所以这个时候你就要思考一件事,我能否把这条线给它干掉,比如说这个键盘的存在,因为这条线只要不存在,OK我的闭环就没有了。

那这个时候你就要思考另外一件事了,同学们什么事情呢,我这是要去查找我们容器里面是否有A对象,那你告诉我在整个容器的创建过程中,我在整个对象的创建过程中,到底有没有A对象,就执行到这步的时候。

有没有A对象有吗,有吧其实是有的吧,好吧,哪创建A了,在刚开始的时候,我们在执行前面这块的时候,其实我已经把A对象给创建出来了,只不过此时的A对象,它不是我们理解的那种完整对象,是一个非完整对象。

所以此时我来给大家一个描述,就是你们在很多帖子上看到的一个描述,第一个描述什么呢,叫成品对象,第二个叫半成品,半成品,什么叫成品,什么叫半成品呢,很好理解,所谓的成品指的是完成实例化且完成初始化。

那什么叫半成品呢,也是一样的,叫完成什么实例化,但未完成初始化来这两个东西能理解的,同学给老师扣一能理解吗,什么问题吧,很简单的一个知识,所以当我拿过来这块之后,你会发现此时我在找A对象的时候。

A对象实际上是有的,那你告诉我A对象现在是成品还是半成品,成片是半成品,半成品吧,我说了,不是完整对象吗,所以是个半成品,那这个时候就会有一个问题,同学们听好了,我下面这段话的描述。

如果只有了某一个对象的引用,那么能否在后续步骤的时候,对该对象进行赋值操作,能还是不能字少吗,你们看这字再大一点,看的东西能理解吗,如果我只有某个对象的引用,能否在后续的时候给它进行赋值,可不可以。

可以吗,因为你在堆里面生存的空间,说白了就是一个地址,我只要有一个指向性的一个地址,那好了,我就可以干嘛,拿到对自己的引用来进行对象的一个复制操作,用完了吗,对这个步骤是可以的,如果可以的话好。

那现在你要去想一件事了,想什么事,我们再把刚刚那个步骤重新去执行一遍,刚开始我先去创建A对象,创建完对象之后,紧跟着叫实例化对象,B等于N,我现在把这个对象我放到一个结构里面去,什么结构呢。

在中间这块我放一个map结构,这可以吧,map结构在结构里面,刚开始我放的时候,因为现在上创建出A对象了,所以K的值就是我们的A没问题吧,我问一下现在的A是什么状态,成品还是半成品啊,成品还是半成品啊。

半成品吧,我把这个半成品对象先记录到我的map里面去,或者说先放到我们map结构里面去,把这来连起来,紧跟着我开始给A对象里面的B属性,进行赋值操作,在赋值的时候,紧跟着我要去判断容器里面有没有B对象。

同时我判断一下当前的缓存里面,它有没有B对象,我们通过这个判断,你能判断出来,这里面我中间画了个map,里面它包含了B对象吗,看有没有对象,对不上有吗,没有吧是吧,没有没有的话好了。

我紧跟着往下面走到这一步,叫创建B对象,当我执行完实例化B对象之后,他紧跟着我往上,我也连一条线过去,那此时我可以把我们的B对象也放进来,B冒号它也是一个半成品,没问题吧,我把B对象也放进去了。

当我把B对象也放进去之后,紧跟着我开始给B对象的A属性赋值,那么我这块在进行查找的时候,我能否从这个容器里面去找到,我们当下的A对象,你告诉我怎么取到,真难对啊,算了不对了好吧,那么能吧。

如果我这样可以取到这个对象的话,你告诉我我这条线还有必要存在吗,明白了吧,我是不是把它给干掉了,改了之后好了,我取出了我们的A对象,当我取出A对象之后好了,我把A的属性给它赋值,当它赋完值之后。

你告诉我现在我们的B是成品还是半成品,成百万成品成品吧,因为你实例化出来都完成了对吧,所以这时候有一个B的冒号,我们叫成品对象,是这意思,然后呢再跟着往回走走走走,走到这块。

刚刚我为什么要创建P对象来着,我创建B对象的原因是什么,是为了给A里面的B属性赋值,现在我的B对象已经创建完成了,并且变成了一个成品对象了,你告诉我,我能否给我们的A对象里面的B属性,进行赋值了。

能不能,可以吧,是不是可以,你先不要先不要管三个缓存里面放什么东西,你跟着我的思路去走,就这个时候,我可以给A对象里面的B属性赋值了,那赋完值之后,我现在的A它是成品还是半成品,A乘以两半成品,成品吧。

那我是不是可以把我们的A对象,我也放在这个地方,A冒号重新,那你告诉我,当现在这个步骤完成之后,我的ab对象是不是都已经创建完成了,我都创建完成之后,你告诉我,我还会出现我们刚刚说的闭环问题所在吗。

还有闭环吗,不会吧,这闭环就没有了,是变化没有了,所以你来告诉我,我们在解决这个循环依赖问题的时候,它最本质的点在什么地方。

在什么地方,这LP跟OP有什么关系,慢哈中间一个缓存吧,所以为什么要使用缓存来解决这个东西,其实最关键的点并不在于这个map map。

只是为了帮我们把这些对象提前放到一个地方,这还不是最主要和最关键的,最关键是什么,最关键的是叫实例化和初始化是分开执行的,这才是最本质的东西,就像红桃六说的,红桃六说的叫实例化和初始化去分开。

能懂能懂我意思吧好吧,所以它是分开执行的,所以他能够解决这个问题,当然这个东西啊,我只是画了一个简单的图示,通过图的方式来给大家解决,图之后一定看到会有问题,老师你这个map里面A有成品有半成品。

B有成品有半成品,这肯定是不对的,好吧,我们要怎么去解决这个问题,或者说我要去怎么来分割我们队的一个缓存,那这个时候你就想,我能不能把不同类型的对象去,放到不同的Mac结构里面去,可以吗。

这是不是就可以做一个最最最基础的分类了,明白这意思了吗,所以这个下面我们要思考的一件事啊,但是就算我要把这个东西按照类别来分类的话,你也会发现其实我好像需要两个map,就够了,一个map放半成品。

一个map放成品,这就够了,我完全不需要用三级缓存啊,我为什么一定要说是使用三级缓存,来解决我们的循环依赖问题呢,所以这是下面我们要探究的一个问题点,我把这些东西给大家标注个颜色,你可以看到一件事情。

他们的执行步骤其实都是差不多的,这不就是对对象整体的一个创建过程吗,是差不多的啊,把这东西好好搞清楚,那把这个图先说这个图能理解的,来给老师扣个一,能理解吗,图啊是我带着你们引导你们的思路。

然后呢去进行了一个解释,那这个实际上是不是这样的,我们来进行一个验证,好吧好吧,怎么验证,我说了,我们一定要去看代码,如果你想把这东西理解透了。

你不看代码简直就是耍流氓,所以代表你是必须要看的好吧。

怎么看这东西,先问第一个问题,谁真正的见过三级缓存到底指的是哪,三个Mac结构,谁能告诉我,都在说三级缓存哪哪三个满分,这是半成品。

我上面不是解释了吗,成品表示什么叫完成实例化,写完成初始化,什么叫半成品,叫完成实例化,未完成初始化,我不解释这东西了吗。

系列 5:P37:37、图解循环依赖 - 马士兵学堂 - BV1E34y1w773

好吧废话不要这么多,下面我们来模拟一下AB两个对象的创建过程,因为啊我现在有两个AB对象了,那我在创建之前就意味着一件事我怎么做呀,首先第一个步骤画一个图啊,看看这个图,第一个叫创建A对象,这没问题吧。

好吧,我问一下创建A对象的时候,要包含几个步骤和环节,第一个是什么,第一个是啥反射实例化吧,我们还是我刚才说了啊,我们说的时候只说这几个步骤,实例化也就是说对吧,实例化就是绿化A对象。

当我完成A对象的实例化操作之后,我的问题是这里面的B属性此时是等于什么值,B是什么值,默认值吧,等于空对吧,然后紧跟着第二个步骤要干嘛,是不是要给,A对象的B属性,变形赋值的,那么在进行赋值的时候。

大家应该知道容器里面的对象默认是单位的,也就是说有且仅有一个对象,这下面我会去判断一个东西,判断啥,判断容器中是否有B对象,那是否有的话,就意味着一定有一个事,下面会有两个路径,有或者没有吧好吧。

来往上写,如果没有,如果有有的话怎么办,如果有这个值,那OK我直接赋值即可吧,是不是直接完成赋值了,赋完值之后好了,把它给回去结束了对吧,那如果没有呢,嗯没有没有,它意味着下面我干嘛要创建B对象吧。

是不是意思,而创建B对象的时候,因为你要遵循完整的bean的生命周期,所以整体的流程和步骤是一模一样的,所以第一个步骤干嘛叫实例化B对象,当我把B对象实例化完成之后,紧跟着里面的A属性等于什么值。

空值吧,依然是默认值等于N,当N完了之后,紧跟着再进行一个事,叫做给B对象的A属性进行赋值,那赋值的时候,这上面一样必然要经过一个判断,判断一下你到底是判断一下,判断容器中是否有A对象。

那我既然要判断一样两个步骤,要不然有,要不然没有,如果没有嗯,先写有吧,叫直接赋值即可,然后这条线连过来,写一下,有这样的,如果没有,没有就这个步骤,这能理解吗,我刚刚画的这个步骤没问题吧。

所以在我刚刚画的这个步骤里面,你能不能看到一个非常简单且直接的闭环操作,这么长吗,小一点,看这个你看到了吗,这就是我们说的循环依赖吗,在整个整个执行过程里面,它形成了一个闭环嘛,是不是这意思,死循环吗。

那死循环其实就是我们要解决的这个,循环依赖的问题,这是为什么面试中经常问这个问题,好吧,那我们怎么样去解决这个问题啊,很多同学在遇到这样问题的时候,说老师完了形成闭环了,这个闭环我要怎么解开。

你记住所有的闭环不只是循环依赖,任何地方,你在遇到闭环的时候,你要想解开这个闭环思考的维度是什么,在哪个地方是最后一个步骤落成了闭环,我们刚刚画张图的时候,在这这个步骤是不是形成闭环。

假设这条路径如果没有的话,把它删掉,如果没有的话,还会有这个闭环吗,不存在了吧,所以这个时候你就要思考一件事,我能否把这条线给它干掉,比如说这个键盘的存在,因为这条线只要不存在,OK我的闭环就没有了。

那这个时候你就要思考另外一件事了,同学们什么事情呢,我这是要去查找我们容器里面是否有A对象,那你告诉我在整个容器的创建过程中,我在整个对象的创建过程中,到底有没有A对象,就执行到这步的时候。

有没有A对象有吗,有吧其实是有的吧,好吧,哪创建A了,在刚开始的时候,我们在执行前面这块的时候,其实我已经把A对象给创建出来了,只不过此时的A对象,它不是我们理解的那种完整对象,是一个非完整对象。

所以此时我来给大家一个描述,就是你们在很多帖子上看到的一个描述,第一个描述什么呢,叫成品对象,第二个叫半成品,半成品,什么叫成品,什么叫半成品呢,很好理解,所谓的成品指的是完成实例化且完成初始化。

那什么叫半成品呢,也是一样的,叫完成什么实例化,但未完成初始化来这两个东西能理解的,同学给老师扣一能理解吗,什么问题吧,很简单的一个知识,所以当我拿过来这块之后,你会发现此时我在找A对象的时候。

A对象实际上是有的,那你告诉我A对象现在是成品还是半成品,成片是半成品,半成品吧,我说了,不是完整对象吗,所以是个半成品,那这个时候就会有一个问题,同学们听好了,我下面这段话的描述。

如果只有了某一个对象的引用,那么能否在后续步骤的时候,对该对象进行赋值操作,能还是不能字少吗,你们看这字再大一点,看的东西能理解吗,如果我只有某个对象的引用,能否在后续的时候给它进行赋值,可不可以。

可以吗,因为你在堆里面生存的空间,说白了就是一个地址,我只要有一个指向性的一个地址,那好了,我就可以干嘛,拿到对自己的引用来进行对象的一个复制操作,用完了吗,对这个步骤是可以的,如果可以的话好。

那现在你要去想一件事了,想什么事,我们再把刚刚那个步骤重新去执行一遍,刚开始我先去创建A对象,创建完对象之后,紧跟着叫实例化对象,B等于N,我现在把这个对象我放到一个结构里面去,什么结构呢。

在中间这块我放一个map结构,这可以吧,map结构在结构里面,刚开始我放的时候,因为现在上创建出A对象了,所以K的值就是我们的A没问题吧,我问一下现在的A是什么状态,成品还是半成品啊,成品还是半成品啊。

半成品吧,我把这个半成品对象先记录到我的map里面去,或者说先放到我们map结构里面去,把这来连起来,紧跟着我开始给A对象里面的B属性,进行赋值操作,在赋值的时候,紧跟着我要去判断容器里面有没有B对象。

同时我判断一下当前的缓存里面,它有没有B对象,我们通过这个判断,你能判断出来,这里面我中间画了个map,里面它包含了B对象吗,看有没有对象,对不上有吗,没有吧是吧,没有没有的话好了。

我紧跟着往下面走到这一步,叫创建B对象,当我执行完实例化B对象之后,他紧跟着我往上,我也连一条线过去,那此时我可以把我们的B对象也放进来,B冒号它也是一个半成品,没问题吧,我把B对象也放进去了。

当我把B对象也放进去之后,紧跟着我开始给B对象的A属性赋值,那么我这块在进行查找的时候,我能否从这个容器里面去找到,我们当下的A对象,你告诉我怎么取到,真难对啊,算了不对了好吧,那么能吧。

如果我这样可以取到这个对象的话,你告诉我我这条线还有必要存在吗,明白了吧,我是不是把它给干掉了,改了之后好了,我取出了我们的A对象,当我取出A对象之后好了,我把A的属性给它赋值,当它赋完值之后。

你告诉我现在我们的B是成品还是半成品,成百万成品成品吧,因为你实例化出来都完成了对吧,所以这时候有一个B的冒号,我们叫成品对象,是这意思,然后呢再跟着往回走走走走,走到这块。

刚刚我为什么要创建P对象来着,我创建B对象的原因是什么,是为了给A里面的B属性赋值,现在我的B对象已经创建完成了,并且变成了一个成品对象了,你告诉我,我能否给我们的A对象里面的B属性,进行赋值了。

能不能,可以吧,是不是可以,你先不要先不要管三个缓存里面放什么东西,你跟着我的思路去走,就这个时候,我可以给A对象里面的B属性赋值了,那赋完值之后,我现在的A它是成品还是半成品,A乘以两半成品,成品吧。

那我是不是可以把我们的A对象,我也放在这个地方,A冒号重新,那你告诉我,当现在这个步骤完成之后,我的ab对象是不是都已经创建完成了,我都创建完成之后,你告诉我,我还会出现我们刚刚说的闭环问题所在吗。

还有闭环吗,不会吧,这闭环就没有了,是变化没有了,所以你来告诉我,我们在解决这个循环依赖问题的时候,它最本质的点在什么地方。

在什么地方,这LP跟OP有什么关系,慢哈中间一个缓存吧,所以为什么要使用缓存来解决这个东西,其实最关键的点并不在于这个map map。

只是为了帮我们把这些对象提前放到一个地方,这还不是最主要和最关键的,最关键是什么,最关键的是叫实例化和初始化是分开执行的,这才是最本质的东西,就像红桃六说的,红桃六说的叫实例化和初始化去分开。

能懂能懂我意思吧好吧,所以它是分开执行的,所以他能够解决这个问题,当然这个东西啊,我只是画了一个简单的图示,通过图的方式来给大家解决,图之后一定看到会有问题,老师你这个map里面A有成品有半成品。

B有成品有半成品,这肯定是不对的,好吧,我们要怎么去解决这个问题,或者说我要去怎么来分割我们队的一个缓存,那这个时候你就想,我能不能把不同类型的对象去,放到不同的Mac结构里面去,可以吗。

这是不是就可以做一个最最最基础的分类了,明白这意思了吗,所以这个下面我们要思考的一件事啊,但是就算我要把这个东西按照类别来分类的话,你也会发现其实我好像需要两个map,就够了,一个map放半成品。

一个map放成品,这就够了,我完全不需要用三级缓存啊,我为什么一定要说是使用三级缓存,来解决我们的循环依赖问题呢,所以这是下面我们要探究的一个问题点,我把这些东西给大家标注个颜色,你可以看到一件事情。

他们的执行步骤其实都是差不多的,这不就是对对象整体的一个创建过程吗,是差不多的啊,把这东西好好搞清楚,那把这个图先说这个图能理解的,来给老师扣个一,能理解吗,图啊是我带着你们引导你们的思路。

然后呢去进行了一个解释,那这个实际上是不是这样的,我们来进行一个验证,好吧好吧,怎么验证,我说了,我们一定要去看代码,如果你想把这东西理解透了。

你不看代码简直就是耍流氓,所以代表你是必须要看的好吧。

怎么看这东西,先问第一个问题,谁真正的见过三级缓存到底指的是哪,三个Mac结构,谁能告诉我,都在说三级缓存哪哪三个满分,这是半成品。

我上面不是解释了吗,成品表示什么叫完成实例化,写完成初始化,什么叫半成品,叫完成实例化,未完成初始化,我不解释这东西了吗。

系列 5:P38:38、debug循环依赖的前置准备 - 马士兵学堂 - BV1E34y1w773

对昨天如果你昨天听课了,昨天上课的时候,其实我再给大家看这东西。

今天我把这东西同样给大家拿出来,怎么看呢,把东西关掉来,我们搜一个东西叫default,Being rejection,在当前这个类里面,你往上翻,最上面这块有三个具体的map结构,这是啥玩意儿。

我把这三个东西给大家截出来,源源码里面啊。

本来源码里面写的是私有的,我改成了公有的,改公有的原因是什么,是因为我修改源码了,一会给大家说好吧,就给大家说,然后我们把这头粘过来,实际尺寸,这就是我们经常做到的东西,一级二级三级缓存。

也就是说这里面实际上指的是这三个Mac结构,你是需要对这三个map结构,有整体的认知和把控的,好吧,这三个Mac到底什么意思啊,也非常简单,这个叫什么,大家注意了。

上面那个叫singleton object,Singleton object,它表示是一级缓存,改一下颜色。

他表示一级缓存,而我们下面第二个这东西,我们称之为什么叫三级缓存,好再往下走,一个这玩意儿叫二级缓存,他没有按照我们说的这个顺序来定义好吧,你知道这东西可以了。

一级缓存叫singleton objects,二级缓存好吧,叫做early sequent objects,三级缓存叫做snon factories,那下面我紧跟着就会问一个问题。

这三个缓存结构有什么样的区别,有区别吗,为什么有的是韩信吧,有人还信办法,现实安全不安全吗,啊一级和二级,一级和二级是线程不安全的,所以要加SCHNET的,而三级是安全的,所以要加用哈希Mac就可以了。

这在它后面代码的操作,我一会看下就知道了好吧,那有什么区别,先说有区别吗,有吧,第一个区别就是你们说的,老师看后面的创建对象不一样,一级二级是content哈希map,三二级三级是哈希map。

除了这个之外,比如说老师还有容量,一级2256,二级16,三级16,为什么一级更大一点对吧,那些点不是最主要的,最主要的东西是什么,就同学们说的这个玩意儿,你看一下。

一级和二级里面放的东西都叫object对象对吧,而三级里面放了一个东西叫object factory,那下面就要解释一下什么叫object factory,不知道怎么理解啊,能叫这玩意吧,它是个啥。

它具体要表达的到底是什么样的一个意思啊,这东西不要不要直接翻译,同学们不要叫对象工程,它是什么,它是一个函数式接口,如果接触过拉姆达式,同学应该知道它是一个函数式,接口好吧,有且仅有一个方法。

明白意思吧,那它还有什么用处呢,可以啊,当做方法的参数传递进去,也就是说当指明此类型参数的方法好吧,可以传入,传传传传入一个拉姆达表达式,在执行的时候并不会执行那个表达式,马上再好。

不调用get object方法的时候才会去调用,那么表达式处理的逻辑,这东西如果谁不清楚的话,下去去补充对应的基础实例,可以看一下拉姆表达式对应的一些点啊,我们这儿不再浪费这个时间。

你就记住为啥看拉表达式你就知道了,好记住了,我们在指定方法的时候,你可以传一个object factory这样一个类型,那么在传参数的时候不可以不是一个具体的值,而我可以传一个拉姆达表达式进去。

当把lab表达式传进去之后,我再调用这个方法的时候,它并不会立刻执行,只有在调用这个get object的时候才会执行这块,你可以好好去看一下,这个代码叫get factory,我们可以直接点过去。

他们叫functional interface,好吧,然后里面有个get不get好,通过这个方法来进行调用,还是编程的一个思想,接下来自己看好吧,我不再讲这东西了,属于比较基础的东西。

所以你要把这个点记住,因为我们三级缓存存在的意义和价值,说白了就变成这玩意儿最核心的点,其实就在于这块好吧,OK把这三栋先记住,那把这三栋记住之后,还有还有啥,我们要实际的去模拟一下ab对象。

在整体的整个创建过程中,它到底在三个缓存中是如何流转,所以呢我为了方便给大家画图,我再画几个框,这是一级,写不到字了过来,一级缓存,下面是我们的二级缓存,后面是我们三级缓存,我把这三个缓存结构放这块。

然后我们在整体对象创建的时候,我会往后面加上我们对象整体流传过程,你要跟着我的思路往后慢慢捋,当然在最开始的时候,这些对象一定是等于空的,这没问题吧,放到这儿啊,后面我会往后面画框,你跟着我的思路。

把这个对象的流转也要搞明白了,那这个时候下一步我们紧跟着进行一个操作,干嘛要进行debug,我知道很多同学,我问一下,有多少同学自己debug源码进行过这个操作,同学扣一没进过这个操作,扣二,好了。

大部分同学偷的都是二,为了方便大家去理解,我们这儿先做一个我提前的预告,在整个对象的生命周期里面,我们在创建对象的时候,大概有几个非常重要且标准的方法,你给我记住了啊,一共就六个方法名字。

你把这六个方法名字给我记住,第一个方法名字叫什么呢,叫get ban,这是第一个,第二话名字叫do get bean,第二个,第三个叫create be,第三个记住第四个,叫do create b。

然后紧跟着后面第五个叫create bean instance,然后第六个,叫popular be,来这六个方法能不能记住,这没问题吧,我就靠大家的记忆力,脑瓜子记住这个方法没问题吧,这还是很容易的。

也就是说我们一会再进行debug的时候,你其他任何的逻辑代码你都不需要看,你只需要给我记住这六个关键方法,当一个方法执行完成之后,我希望你能去放代码里面,去找下一个方法来处理逻辑就完事了。

因为原版里面代码很多,你要一行一行去看,太浪费时间,同时很多同学可能跟不上,所以我们要记住这东西,方便你来带着整体的流程,同时我也做一个预告,在原版里面会有很多套娃的存在,当你看到套娃之后。

别觉得奇怪啊,很正常的一件事情,OK好了,这些东西聊完之后,前期准备工作做完之后,我们开始DIY代码,什么debug,debug之前,我一定要去给大家看一下我们的原始代码啊,我这写了一个包叫SL好吧。

里面定义一个A对象,你可以看到A对象非常简单,里面只有一个B属性,提供了一个B属性的set get方法,有一个合作方法,有一个TOSTRING没了好吧,同时有一个B对象。

有A里面的set和get方法没了好吧。

然后我在配置我们具体的配置文件的时候,也很简单,下面啥都没定义,配置了一个B对象,A配置了一个B对象B,然后A的属性B好吧,引用了B,然后呢B对象的属性A引用了属性A就这意思,这能看懂吗。

来这个代码能看懂,同学给老师扣一,这个很简单很基础的东西了,你这个东西必须要会好吧好了,这之后我们开始运行整个应用程序。

系列 5:P39:39、循环依赖的详细debug过程 - 马士兵学堂 - BV1E34y1w773

啊这看了之后,我们开始运行整个应用程序,打开我的test test里面也非常简单,我这打一个点,打开之后开始右击第八个,我错了,为啥写配置文件,你可以用auto wear,没关系,我为什么讲配置文件。

讲配置文件的原因非常简单,因为配置文件是最原始最老的方式,它也是最完善的功能体现,如果你能把配置文件的方式搞清楚了,那么你再看注解也好,看配置类也好,都会非常轻松,因为它是最麻烦的,你明白吗。

他是最麻烦的好,所以我想带你们看最麻烦的东西,捡东西你们自己看啊,所以刚开始会提到这个地方,我们点F7进去创建对象,这是一个WEBLOGIC,等于bug,不管它点FC进到我们的构造方法里面去。

再点MC进来,上面的东西super不用说了吧,要用父类的构造方法干什么事,不管爱干嘛干嘛,我昨天给大家说过了,看源码的方法论了,不要每一个方法都点进去,你通过方法名字,知道我调用父类构造方法就完事了。

爱干嘛干嘛,不管他下一个叫sconfig locations,什么意思,要设置配置文件路径,传过来的就是我们的CIA的XM对吧,我只要把配置文件传进来,它会设置到我们指定的位置里面去就OK了。

明白意思吗,还是一样的,你别写进去看好吧,里面数据逻辑还多呢,你要一层层往里边点,我告诉你一会就点蒙了很多,别往里面点啊,学会适可而止,控制住自己的手好吧,不用管它,再往下走。

跳到我们的REFLESH方法,我昨天也说过这件事了,我说如果你能把abstract application,context里面的REFLESH方法,你如果能看懂的话,我告诉大家。

基本上源码已经从源码已经接到了,基本上就够了好,但是还是那个里面逻辑还是很多的好吧,这块前面有一些准备工作好吧,要做一些容器的初始化好吧,赋值啊,包括像监听器啊这些东西操作,不管它。

我们直接到电脑代码里面去这样,因为从这个步骤开始,才正儿八经的去创建我们的对象,都这直接跳过来,有的老师是这样吗,是不是这样,我们可以做一个验证,刚刚我带你看过了1233缓存是什么。

一级缓存叫singleton object,二级缓存叫early signal objects,三级缓存叫signon factories,所以你打开当前这个第八页面之后,找到我们的b factory。

在bean factory里面找C工程OBJESS,找一下往哪看,四点共同JECT里面有对象吗,有吗,点开有ab对,有ab对象吗,这里面提现这五个对象是什么,是容器需要对象并不是我们创建的A和B对象。

就现在容器里面没有AB对象,你再看二级缓存零吧,三级缓存零吧,我错了,对象还没开始创建,所以现在这个步骤一定都是空,不管他,我们点F7进去进去好吧,进来之后上面有一些属性值的判断,你可以直接跳过好吧。

这些步骤也不是创建对象的,我们直接到这一行,从这一行开始,终于进入到我们创建对象的流程里面去了,所以再点F7进来,进来之后来问一个问题,刚刚的配置文件里面,我问一下,我需要创建几个对象。

我需要创建几个病,俩吧就俩吧,一个A1个B没别的东西了,又是什么东西好吧,所以当我识别到之后,我点开我的创业类,你会看到它会把be对象的名字给你,放到一个集合里面去。

是a release里面就是我们的A和B两个对象,我说了AB两个对象啊,它没有明显的先后创建顺序,也就是说我可以先创建A也可以先创建D,这个无所谓啊,对于我们当前应用程序而言,0号位置是A嘛。

所以刚开始取的时候取的是A对象,我先把B内取出来好吧,当我取到B内部,A等于之后干嘛了,是不是该创建我们的A对象了,但是注意了,同学们在创建任何对象之前,我都要去做一个预先的判断,判断什么东西啊。

我需要判断啥,谁能告诉我,对容器里面是否有对象,所以往下走走,走到这行代码里面叫get be,我要先去容器里面获取一下,我到底有没有当前的A对象,所以从这开始,进入到我们核心的处理逻辑里面去了。

比如我刚刚给你说的第一个方法叫A对象,叫叫get in,这是我们第一个叫get in,get完之后点F7进去到第二个方法叫do get be,好吧,这提个醒以后,你们再看一些框架源码的时候。

如果你看到了以do开头的方法,一定要警醒一下自己,为什么,因为你不开图的方法,基本上是实际干活的方法,也就是说在这个do开的方法里面,包含了非常多的真实的处理逻辑,就这是我们要小心的留意的。

OK我再点M7进去,进来之后先获取一下我们对应的名字吧,获取完名字之后来了一个东西叫get singleton,什么叫get singleton,电瓶之翼啊,我昨天讲过电瓶之翼,为啥注释是黄色的。

再自己改的颜色亮一点,好看一点,获取单单单单对象吗,我们现在能获取到A的单例对象吗,不是一级缓存的名字啊,这是一个方法叫获取单对象能吗,你都没创建,你哪来的获取不能,所以当这个步骤执行完成之后。

你会发现这个对象等于空,如果等于空意味着什么事,我是不是必须要去创建A对象了对吧,你要创建了吗,也没有吗,没有你只能创建吗,别人不会给你,所以我再往下走,下面有一堆的逻辑判断,你可以直接跳过。

不用管它好吧,不用管他,不用管它,我们直接找到一行代码里面去,在这行到这块之后,你会发现一个方法叫什么,叫create be,对吧,终于看到了创建对象这个方法名字,这是我说的第三个方法,然后往下走一步。

又来到一个方法里面,叫get singleton,这个时候我希望你能好好留意一下,get singleton这个代码,这是刚刚给大家说那个object factory,这个东西可以拿出来。

让你好好看一下,拿过来,我把这些乱七八糟的注释给干掉,是不是没啥用,同学们注意看,在当前这个方法里面我放什么东西,get signment是方法名字对吧,b name是方法的第一个参数就是A。

然后后面我出来个六,这玩意,这玩意是啥,就是我们的拉姆达表达式啊,它对应的就是我们刚刚那个object factory函数式接口,它的一个调用过程。

所以当我开始进到这个singleton方法里面去的时候,我这里面的current d并不会真正的去执行,就来点FT进去,进到这个方法里面去,调完之后,这里面依然有一堆的判断逻辑,我刚刚前面写过了。

我说这个东西要通过什么来调用来着,通过get object的方法来进行调用,所以此时我们在看源码的时候,我就要去找了,往下找找找找一堆的判断,跳过去,不管它,你不要好奇,看这东西没用好吧,直接到这一行。

叫singleton factory,singleton factory是啥呢,往上翻是我们刚刚传过来的参数,传过参数是啥,是我们的lambda表达式,所以此时当我在调用这个get object的时候。

你告诉我实际执行的方法逻辑是谁,不要跟三熊猫跟三级缓存没关系,没到那是我们的BREAKBEAN方法,所以我点一个F1进去,是不是到CREDB了,到create in方法了,从这个步骤开始。

我要真正的去创建我们对象,然后再点F7进去,这里面又有一堆的逻辑判断,我说了这些逻辑判断,你可以不管,我问一下第四个方法名字叫什么,他们听好了,这东西啊,很难理解,我在带着你去debug源码。

如果你都觉得很难理解的话,你自己去看,你会变得更懵,所以现在晕,别着急,跟着我的逻辑线去慢慢往后走,你会把这些源码给理解透了,没大家想的那么难啊,所以第一个方法叫do cret b。

我们下面情况找了找找找找,找好了,找到了,第四个方法叫do create be,我刚刚也说过了,不开合作方法都是实际干活的方法,所以我们再点F7进去之后,终于到了实际创建bean对象的一个处理逻辑吧。

好意思,往下走往下走,往下走,往下走,到这个方法,那么到这一步之后,就是我们说的第五个方法吧,来这个方法叫什么,叫pread bean instance,叫创建bean实例。

说白了就是我们创建对象对象名字是谁,是A嘛,所以我创建出来的就是我们的A对象,对往下走一步,你会看到现在我获取到的A对象叫什么,叫a at1655里面的属性B是什么,是空的吧,是不是空的好吧。

所以这样我也要做一个标注了,我先创建出一个A对象,叫a at1655,此时的B等于N,我问一下,现在我有往三个Mac结构里面放东西吗,现在我要把三个map里面放东西吗,没有啊。

还没我只是把当前对象给创建出来了啊,所以这是什么,相当于我们刚刚在这张图里面,我只完成了实例化对象,还没开始给里面进行赋值呢,把头理解错了,所以我先把它扔一边,先放这个地方,当我放这个地方之后。

中间依然有一些逻辑判断,不管它我们该找干嘛了,是不是该去填充我们的属性了,所以来到我们的第六个方法里面去,那第六个呢叫populate bean。

但是在populate bean之前有这样的一个处理逻辑,叫at singleton factory,当你看到这个方法之后,别着急,猜这个方法干嘛的,你注意看它的参数,第一个叫冰name。

第二个我又传递了个什么玩意儿,什么玩意儿,拉姆达表达式,这个拉姆达式我要给大家站出来,因为这东西才是我们解决循环依赖的,最关键的问题所在,我需要把它给粘出来,方便我们一会来进行查看,算出来放这儿好吧。

放完之后来往下看,干什么事呢,很简单点,M7进去,就这个方案里面去,进完之后往下走,里面有一些异常的处理,不是那个线程的处理操作,不管它第一步叫this singleton factories put。

这是往哪个缓存里面放,哪个三级缓存吧,但是你注意三级啊,不是二级啊,三级,但是你注意往三级缓存里面放的是啥,K是我们的a value是个什么玩意儿,什么玩意儿,拉姆达表达式,它并不是把我们的A对。

他并不是把A对象放进去,留答案,他并不是把A对象放进去的,而是放了一个,然后表达式,所以我这在进行标注的时候,我也应该这样来标注它,什么叫做刚开始K冒号放的是我们的A对象,对吧。

而value放的是什么调lambda表达式,哪个拉姆表达式呢,就是下面这块我放这了,下面这个对象把它放进去了,搞清楚没放对象好吧,现在没放对象,OK完了之后来往下走。

叫this rise early singleton object remove,而二级缓存给移除掉,二级可能现在里面本来就是空的,啥都没放,就不管它,再往下走,就reject singleton。

当你所有的bean对象放完之后,会有一个已注册的bean对象把它放进去,就这相当于是一个已注册并对象的一个集合,不管它没啥用,跟三级缓存没关系,跳过也就是说在对象属性设置之前。

我已经把K等于a value,等于拉姆表达式的一个东西,放到了三级缓存里面去,注意我放的并不是A对象,而是包含A对象的一个拉姆达表达式,来这能听懂的,给老师扣一,能听懂吗,好了继续跟没到精彩的地方。

当这执行完了之后,我们紧跟着再来干嘛,下一个步骤叫popular bean,你注意popular be,poplar be叫填充属性,你可以翻译一下,说白了就是给我们的属性来进行赋值好吧。

现在我们的A对象还是这玩意儿,A艾特1655好吧,B等于空,没做任何变化,然后从这个步骤开始,我要开始填充我们对象了,这里面有一堆的逻辑操作,你都不用管它,我们直接跳到最后一行,因为只有在最后一行。

这块才是具体的属性值的操作,中间这块都是检查判断啊,没啥用,所以我直接跳过来了,到最后明白了吧,直接跳过来,跳完之后点F7进去啊,进来之后怎么进行属性的赋值啊,走走走走走走走,注意啊,我先问你个问题啊。

A里面有几个属性,一个吧只有一个B属性,所以我要找到我们对应的属性值,所以往下走走走走,走到这往下看,叫PV,PV就是我们的属性值的集合,好吧,里面只有一个属性值B,所以当我重复完成之后好了。

我获取到我们属性名字了,等于B好在下一步我该干嘛呢,叫PV点get value,正常情况下,你告诉我我这个get value应该获取到一个什么值啊,不知道有什么值,那么好吧,但是当你执行完成之后。

你会发现他这获取到一个对象,这个对象你们可能没见过叫什么,叫raw time bean reference,记住啊,叫wrong time being reference,把这个名字给我记住。

因为后面我们会用到的东西,装上b reference,大家只记住叫运行时的一个并引用,这样你是必须要知道的好吧,当你知道并值之后往下走,来到这行叫value reserve resolve value。

If necessary,通过名字判断你告诉我干嘛的,如果必要的话,我要去处理value值了,实际上我们这个value我最想获取的是啥,是不是应该是一个B对象,因为如果我能够获取到B对象的话。

我就可以直接完成我们的布置工作了,但是我现在获取到的是什么,第一个wrong time,并reference一个对象引用,而不是B对象,所以现在我要去处理我们的病B对象了,这是不是需要处理的。

你只从那点F7进去,进来之后,这个逻辑判断,If value instance of wrong time being reference,来告诉我,我们刚刚传过来的value值是不是这个类型。

是不是这个类型是吧好了如果是的话,我能进来,第一步类型强转,强制完了之后到这叫resolve reference,开始处理我们的引用了,我再点F7进去,第一步先获取我们bean类型的bean类型。

这只有一个标签B吗,好返回之后等于空获取标类型,如果他在找他的副工厂里面有什么东西好吧,然后说如果不等于空做什么事,我们再等于空可以跳到这往哪看,同学们关键点来了。

叫string点value of do evute reference get the name,说白了我就是把什么,把我们刚刚传过来那个B参数,给它做一个名字转换,所以这处理完成之后。

我的名字等于谁等于B哎你写不出来了,没事往哪看,这个叫result name,等于谁为B然后当你到B站之后,套娃从此开始了,看下面这行代码叫并等于this beget。

并告诉我这是你第几次看到get并对象,第一次第二次吗,相当于什么事,我现在本来要给A里面的B属性赋值了,我通过我的名字破烂照之后,我发现我没有B对象,所以我现在要干嘛,是要去容器里面查找我们的B对象吧。

回到这张图上,是判断容器里面是不是有B对象,知道这步骤了,从这开始要判断了,来到这还能跟上同学给老师扣一,听好了,这个地方我为什么说它是套娃的开始,因为从现在开始,它的执行步骤。

跟我们刚刚创建A对象的执行步骤,是一模一样的,所以当我点F7进去之后,又回到了我们的第一个处理逻辑里面去,叫get in,Get in,后面的第二个方法叫什么,叫do get be对吧,再减F7进去。

第一步转换名字,第二步叫get singleton,来,问题来了,这个get singleton里面有B对象吗,有没有没有,所以这取出来等于空,当它等于空之后,紧跟着我是不是要去创建我们的B对象了。

对往下走走走走走走走走走走,走到这儿再进到我们的get snon里面,然后里面是什么格式,编码一模一样,DF7进去进来之后找什么,找get object的方法,走走走走。

当我找到get object方法之后,紧跟着我要去调用我们的create bean方法,我再点FC进去,下一个方法是啥,下一个方法是什么,Do create bean,所以往下走走走走。

你这个逻辑看跳过,不管走,走到这叫do cred,是不是进去了,点FC进去,进去之后往下走走走,走到这一步,当我到这一步之后干嘛了,我是不是要去创建我们的B对象了,此时我创建对象是谁,B吧,是该B了。

所以这时候你打开,你会发现我现在已经把B对象创建好了,创建好之后,B是谁,叫bf1995来拿出来,我依然给他扔一边儿,D at1955,此时A属性等于空来,我问一下,它对应我们上面这个图里面。

哪个步骤是这个步骤,我开始完成B对象的实例化了吧,B对象实例化,当我B对象的实例化结束了之后,紧跟着来再进行操作,往下走走走走走走走走走好吧,走走走,走到这一行来告诉我这行干嘛,这样干嘛,放缓存嘛。

往哪放,往三级里面放,放的是谁,当这我往三级里面放的时候,我一样的,我放的对象K他放的谁叫B吧,但是我的value是谁啊,还是那个拉姆达表达式,就现在三级里面都已经包含了,我们的AB对象和AB的名字了。

但是不过我的值是一个拉姆达表达式而已,那这个拉姆达有什么用,一会儿我们再说啊,先把它搞定好了,这波执行完了,所以往下走,大家都这叫populate bean,点FC进去吧,哎还记得干嘛了吗。

现在是不是该给B对象里面的A属性,来进行赋值了对吧,给B对象里面的A属性进行赋值,所以点mt进去进去之后一样,老规矩,直接跳过到最后一行叫apply property values,再点F7进来。

进来之后往下执行我们代码的一个逻辑,找谁找属性名字吗,都跳过跳过跳过跳过,不管它都过跳过跳过跳过跳过跑到这第一步,获取我们属性的名称,往下走,名称是谁,A吧,好紧接着获取我们的value值。

这个时候你再看你获取到的value值是谁,是什么,同学们是不是依然是A吗,怎么会是A呢,你A现在都没往里面放,咋会是A呢,不是A啊,是不是还是一个运行时的并引用,依然是运行时的宾语用啊,没关系。

当我看到运行的宾语中,我也不慌,往下走,是不是该进行值处理了,点F7进去好吧,判断一下你是否是这个类型,很明显我们的value值是这个类型,一旦我是这个类型之后,可以干嘛,是不是可以强制类型。

转完之后开始处理我们的引用,处理的时候步骤一样,第一步get beat啊,没有好吧,然后呢,bin不等于空进入到里面,等于空往下走,又开始获取我们的属性值了,当这儿获取完成之后,我过去了A吧好了。

现在告诉我第几次看到GP方法,第三次第三次了,所以我说了,如果你真正的能把一遍流程跑通的话,你会发现里面基本上都是套娃,它的处理流程,处理步骤几乎是一模一样的,所以不需要慌,好吧,来再点X,这干嘛来着。

我要去找找谁了,现在我要去找谁了,告诉我,找A对象吧,好找A对象,然后我点F7进去又到哪了,do get been对吧,再点F7进去获取名字,然后到这个里面去。

现在问题来了,他到哪了,是不是相当于执行到这个步骤了,执行这个步骤了,来执行这个步骤,能理解,同学给老师扣一,能理解吗,可以吧,能理解的话,来我问一下,这里面有A对象吗,我们现在三个缓存里面有A对象吗。

看着看图有没有。

有没对象的有吗,注意你是没办法从1233个缓存里面,直接去获取A对象的,但是这有一个三级缓存里面有值吧,所以我就干什么事来看看它的处理逻辑,点F7进去,再点F7进去,到这个方法干什么事呢。

第一步从一级缓存里面获取值,一级缓存里面有A对象吗,没有,所以这值变等于空,没问题吧,第二个判断一下,如果这个值等于空,并且叫is singleton time increation,我问一下。

现在我们的A对象是不是在创建过程中,是吧,所以就等于true,我能够进来,进来之后,我从二级缓存里面取,我问一下二级缓存里面有对象吗,看图有没有没有,依然是等于空的,所以跳过这个值是恒等于处的。

他说如果这个等于空值等于true的话,OK我进来pi之后往下看,这是从哪取,第一级吧,这里面有一个synchronized的双重检查,一级怎么是三级呢,一节再走一遍,一阶二阶都取不到之后。

紧跟着我开始从三级缓存里面取对象了,我问一下,从三级里面取完之后,我获取到是个啥,是A对象吗,不是是一个拉姆达表达式,所以你取出来看看,dollar拉姆达艾特1738是一个拉姆达式。

当我把这个拉姆达式取出来之后,我是不是要调我们的get不get了,你告诉我,当我在调这个get object的时候,我执执行的实际的处理逻辑是哪个逻辑。

get early being reference吧,这东西get early be reference,是不是该接他了好吧,然后点F7进去,再点F7进去,到这个方法路径里面。

到这之后你好像看到点东西这个属性名字,我觉得你应该认识叫exposed object来,谁能告诉我什么叫exposed object,翻译过来叫啥,代号叫啥,暴露对象。

这是你们在看帖子的时候看到那个暴露对象,什么叫提前暴露对象,暴露是谁,暴露的是这个玩意儿,这玩意儿干嘛了,来往这看,第一步操作,我先把A对象赋值给了exposed object。

紧跟着我在最后返回的时候,我返回的是expose object,但是中间这一块的时候,expose object有没有可能会改变,有没有可能会改变,可能吧好吧,这里面是不是有处理逻辑改变啥了。

这需要做什么改变吗,需要做什么改变,来我们点到这个方法里面看一眼,点进去,点完之后找实现类,第一个是一个适配器,不用管它,它上面一个类叫abstract,Auto propose,Secreator。

再点进去叫Viper,If necessary,我再点进去叫create propose,再点进去叫propose battery,Get propose,我再点进去get吧,再点进去往这看。

你告诉我干嘛,我这是不是有可能拥有一个判断。

怕什么东西啊,同学们,判断一下我此处是否需要把它改成代理对象,也就是说这个步骤我在提前进行暴露的时候,要不然我暴露的是原始对象,要不然我暴露的是代理对象,来这句话能听懂的,扣一,记住我说要不难。

要么暴露的是原始对象,要么暴露的是代理对象,至于是否是在一项决于什么,绝于当前这个衣服放大能不能进来,我们刚刚的配置很简单,什么都不配,就配了一个AB对象,那个ab对象它需要生成代理对象吗。

需要不需要不需要吗,对这个地方if是进不来的,我直接把谁返回了,把谁返回了,不就是我们的A对象吗,被对象a at1655,把A对象返回回去,当我返回回去之后,你告诉我我能不能取到A对象啊,能不能。

为什么AB没有再这样,你配了吗,因为没配上这对象吗,所以返回原始对象吗,好了,当我返回原始对象之后,紧接着看,就this early signal object put,放哪了,把原始对象放哪了。

二级缓存嘛,所以现在我可以改变一下我们这张图了,拿过来K依然是我们的A,但是value变成什么,叫AAT1655。

问题是现在的A是成品还是半成品,半成品啊,记住了好了,放这半成品,Ok,放完之后紧跟着叫this singleton fast remove,把谁删除了,把那东西删除了,把三级缓存里面的东西给删除掉。

我们这真的删除,给他标个红色表示删除,你把删删除掉,为什么要删除啊,有人想过这事吗,为什么是半成品,你看这个A对象,你的B是等于空啊,你没给B赋值啊,对不对,所以为什么是三级缓存要删除掉啊。

因为你的查找顺序是一级二级三级,如果二级里面有了我,三级还有必要存在吗,没必要明白意思吧,没必要了,这是不是是不是这意思好吧,把这搞清楚了,所以这块我们到这个步骤了,这是为什么三级缓存容量比较小的原因。

原因在这十六十六吧,哇好了,这搞明白了吧,搞明白之后,来现在我的他往回返回返返返回返,回到这步之后,我把我们的为什么浪费,表示一会再说好不好,别着急,我说了,你们跟着我的思路走,不要提前问问题。

你现在都想不通,后面的东西,你没法问问的东西,别问这是我的思路走,我后面会解释的,为什么要放张表达式,我不解释的,别着急,好不好,心急吃不了热豆腐,快点来好不好,我已经尽快放慢这个节奏了,好听好了。

现在我有没有把A对象给取到,计划就能调大了,你放的数据多了,自然而然就扩容吗,它有自动扩容技术,为什么要自己去设置,不需要吗,提到了吧,我刚刚为什么要取A对象来着,我取A对象的原因是啥来着,对不对。

不错了,不好意思啊,所以现在我已经把A对象获取到了,我能不能给我们的B对象来赋值了,你看到了,刚刚没有create命令方法是进不去create病了,所以往回返再往回返再往下走。

现在我获取到了我们的A对象,那我可以干什么事了,我是不是可以给我们的B属性赋值了,在哪赋值很简单,看完啊,看完在这个步骤里面叫BW点set property values。

在这里面可以完成我们整个的复制工作,往下走走走,返回返回,好吧,再往下不到,这就可以了,你再看一下你的B对象,有了吗,是不是有了,有了的话,你告诉我现在的B是成品还是半成品,成品了吗。

虽然这个A里面是B,但没关系,我的B对象已经有属性值了,所以B现在已经成品了,那成品之后往下走走走走,一直往回返返返返返返回来,按照我们刚刚出逻辑,一直往回返反到哪呢,放到这个方法里面去。

叫ADSINGLETON,注意bb signal object是谁,是B对象,然后点F7进去,第一步叫this signon object put,这是几级缓存,一级放的谁B和B对象吧。

所以此时可以得到一个结论,我可以把什么把我们的B对象给放回来了,写一下K冒号是谁B吧,value冒号谁叫b at1995,现在我们的B对象是成品还是半成品来着,刚说过了商品对象好吧,发送过来了。

挪过来之后,紧跟着干一件事,就this singleton factory,三级缓存移除掉,然后呢二级缓存移除掉,是把三级和二级给1921955,这是把二级和三级干掉。

这样我们一样标红B是不是完了来到这儿,不就是成品了吗,赋完值之后不就是成品了吗,对不对好了,登录完之后点进来下一个问题,我为什么要去创建B对象来着,能听好,我为什么要去创建对象来着。

是为了给A里面的B属性赋值,现在我的B对象已经获取完了,我是不是可以给A属性赋值了吧,所以往回返返到这,我现在我已经能获取到我们这个B对象了,往下看,哎看那B艾特1991995就是九,我没写错啊。

那就这写错了,啊好吧,这写错了,所以现在我已经获取到我们对应的B对象吗,那我获取到B对象,而且获取到是一个成品对象,下一步干嘛,是不是该给A属性A里面的B属性赋值了。

所以往回返返返反反反反反一直反写逻辑判断,不管他跳过跳过跳过跳过好叫BW点,Set property value,到那完成之后是不是给B赋值了,所以往回返返一步到这一步,你再看当前的A对象。

A对象里面有没有B有B吗行吧,A里面有B,B有AA有B,B有A,A有B,是不是意味着我的A,B对象对象都已经创建完成了,对不对,所以此时ab都成了成品,但是还没完,怎么做,走走走走走走。

往回返返返返返返到哪,我现在A对象我也创建完成了,转完之后别忘了,还有一个步骤叫ADSINGLETON,ADC干嘛,是不是A还要去丢到我们的一级缓存里面去,把它丢上来,听完之后。

现在我们的A变成了成品对象,然后把二级是不是也给干掉,是这意思啊,是不是删掉,我说让红色表示删除,那你告诉我现在我这个逻辑执行完了吗,听完了没完了吗,没完没有,同学们不要忘了。

刚刚我们为什么要创建A对象来着,我问一下为什么要去创建A对象,初始化,是因为我们在刚开始的这个循环结构里面,我是先取了A,对不对,当我取完A之后,别忘了这个集合里面有两个值,你只是把A处理完了。

现在你的B处理了吗,没有吧,我先干嘛,该出你B的吧,处理B的时候是不是也是一样,我找get in叫do get bean,然后这个步骤你告诉我,现在能不能从一级里面取到B。

能不能从一级里面去取到B可以吧,所以此时我直接获取到B对象,我获取到BD项了,好了,我下面我还需要去重新叫create beam吗,还需要执行这个步骤吗,不需要了啊,他就执行完了。

所以当这个步骤执行完成之后好了,我们整个处理逻辑才算是结束了啊,这是刚刚整个ab对象的创建流程来听懂的。

扣一,告诉大家我我以这样的方式去debug,你们能能能跟上吗,应该没问题吧,好了这能跟上,我告诉大家还有问题,其实告诉大家,现在给大家解释这个流程,它并不是循环依赖里面的最关键的点,最关键的点。

下面我要写的这段文字,描述才是最重要且最关键的点,也就是说那个流程其实非常简单,你只要正常情况下,你听完了,你应该能看得出来,哪怕你跟不出来,你下学之后自己跟着做一遍也能跟上来,这其实并不是主要的。

主要是什么。

系列 5:P4:3、站在巨人的肩膀上:且看语言的发展史 - 马士兵学堂 - BV1E34y1w773

可以这么说,在最开始的语言的发展的历史上,都是沿着对这种bug来来来,更加容易调试的这个方向不断发展,像原来C和C加加的话,大家应该知道这种是什么事实,怎么怎么管理这块内存啊,怎么管理这个指针的呀。

叫手工吗,手工管理,不知道有多少同学是学过C或者是C加加的,有没有有的话,老师扣个一来C语言里面怎么分配一块内存,a memory allocation对吧,当然还有好多好多函数都可以分配啊。

这其中一个BALLOCATION的意思,我就是开始哎,在我们的内存空间里面找了块内存,但是你总得释放它呀,你怎么释放free这个函数就可以把它给释放了,但是我告诉你啊。

也许因为程序里面充满了各种各样的分支,循环啊,各种各样的不同的岔路,它并不是说只有一条路线,所以只有一条路线的话就简单了,我这边分memory allocation完了之后呢,后面马上就把它废掉。

可是在很多种情况下,我是需要判断的,在这种情况下我要把它删掉,在另外一种情况下,我不要把它删掉,我告诉你,这就造成了各种各样各种各样麻烦的bug,所以手工管理内存。

无论是C里面的memory allocation,或者是C加加里面的new和delete,本质上他这这这哥俩是一回事,这两段是一回事儿,都是需要你进行手工管理,手工管理最麻烦的事情就是你不小心忘了删了。

你知道吧,这空间你分配好了,但是你不小心给忘了,你把它给忘了,忘在这了,这时候会会产生什么,告诉我一下,忘记删除,忘记释放,这个呢叫memory lake,这叫内存泄漏,不要不要叫内存溢出。

大哥他没有溢出,它只是泄露了,泄露什么概念,泄露的意思就是这块空间呢虽然说留在这里,但是所有任何其他的程序不能去访问它了,不能使用它,他留在这儿,他没用了,但是别人也不能用,这就叫泄漏了。

如果泄漏越来越多,会发生什么,泄露的越来越多,泄露越来越多,会发生一种现象,就是当新的内存空间要申请的时候来了,我需要申请这么大一块,我突然间发现这里面充满了一个一个动,一个一个动。

而且中间我找不到一块连续的内存,来为我这块内存分配空间了,完蛋这个叫内存溢出,泄露过多的时候容易产生内存溢出,但它本身不叫内存溢出,Optimemory,当然这种的还算是不是不是很严重啊。

大不了我重启一下是吧,你又能跑好长好长时间,所以调优JVM调优最重要的一点叫做重启,每两周重启一次,玩过游戏吗,有的游戏是不是就这样,各位指挥官,我们的游戏服务器将在5分钟之后启动,进行维护。

在此期间不得互相攻击,Good,你们已经学会了第一种调优的常用的方式,当然你不能跟面试官这么说,做过调优吗,做过怎么做的,重启面试官一个大嘴巴子给你抽上来,哪凉快哪呆着去。

这是第一种有可能会产生问题的地方,叫忘记是吧,第二种是什么,第二种叫做,释放多次就是你释放了一次,你delete了他的一次,由于有分支判断各种各方面的情况存在,也许有可能你free了好多次。

delete了好多次,这个有同学说没问题啊,这块空间我不是干掉他一次,没关系啊,我再干他一次吗,不就是尸体让我又干了他一次吗,鞭尸而已,没错,你只是编了个师的问题倒是不是特别大。

但关键是当你干掉他第一次的时候,有另外一个人已经把这块空间给重用了,人家已经又放上有用的空间了,结果呢,你第二次回来又把人这个有用的数据给干掉了,结果另外一个县城就会发现莫名其妙的,你发现没有。

莫名其妙的,你的数据就没了,所以这是为什么说我们多线程这种bug,特别难调的,原因就在这里,你的线程好好的没bug,你懂吗,甚至说你的进程啊,如果进程之间共享的话,你的进程没bug,没有毛病。

你的程序也没有半毛钱毛病,可是很不幸的是,由于有别人家写的bug的存在,他会很容易的把你占有的时候空间给你干掉,你找谁说理一下,好了,这个叫释放多次,产生,极其难以,极其难以调试的bug嗯。

一个线程空间莫名其妙被另外一个释放来,写过C和C加加的人遇到过吗,遇到过的,给老师扣个一,对装装备你莫名其妙的就没了没错,后来呢后来啊,其实谈GC呢开始聊语言的发展历史,我们我帮大家梳理一下这个语言呢。

C和C加加呢它运行起来的效率非常非常的高,呃但是呢它的开发效率很低,有的时候呢有的人呢是片面追求运行效率,但是听我说呃,现在的有一些大规模的软件,它并不是追求你的开。

并不是追求你的你的你的运行效率有多高,也许你运行效率稍微慢一些,我拿那个硬件给你怼上去,我能接受,但是你的开发效率特别低,我就不能接受,别人用Python语言,用java语言,用go语言写一个程序。

仨月写完了,你拿CC加加写,你写一年,等你推出来的时候,市场都没了,黄花菜都凉了,有用吗没用,所以后来产生了很多很多的,对内存管理比较友好的,知道吧,方便内存管理的语言,它方便方便在什么地方呢。

大家注意它方便呢并不是方便,在说那个多线程的情况下啊,没有不会产生什么不一致了,没有野指针了,不是这么回事,它的主要方面在引入了DC这个概念,这里的GC呢指的是garbage collector。

garbage collector的意思是说我哪有错吗,garbage好,Game lecture,Garbage college,叫垃圾收集器,垃圾收集器是什么概念呢,给大家举个形象点的例子。

就是我们平时写写一些小程序啊,就是在这块内存空间里面不断的分配对象,分配对象,然后删除掉删除掉啊,再继续分配,再删除这个对象呢有可能指向另外一个对象,这个对象的成员变量有可能指向另外一个对象。

好在内存空间里面不断地扔这种小线团儿,这小圆圈之间建立各种各样的关联,也许它上下面有好多好多的成员变量,建立建立好多好多的关联等等,会形成一个对象树,这个对象树呢在不断的动态的产生变化。

如果站在内存角度来看这幅图的话,这个图景就是这样子的,原来我们必须得小心翼翼的管理,说这块没用了,我就得小心翼地把它删掉,不能多删,不能不删,但是像这些语言,java语言,Python语言,go语言。

以及原来老早的这个lisp语言啊等等,它引入了一种GC的概念,GC的概念就是说我自己这个程序,我的业务程序我自己不去维护删除这个过程了,我只管分配,只管分配,那么就有必须得有人负责帮你删除。

不然你的内存不就很容易就被占满了吗,好我引入另外的另外的线程,另外的功能好,这个功能叫做GC,叫做garbage letter,叫垃圾回收器,java Python go都有这个这个功能。

它的程序一起来之后,它并不是说只启动你的业务线程,它会同时启动好多线程,这里面的线程就包括垃圾回收线程,OK这个垃圾回收器的功能是什么,就是你不用你再也不用管这个,你你你只管分配内存啊。

应用线程只管分配好垃圾回收器负责回收,当然这是一个很复杂的过程,因为垃圾回收器负责回收那些线条,不是你自己分配的,你怎么知道他什么时候就不用了呢,所以你首先你得首先找出来谁是垃圾。

然后再采用各种各样的方式去回收它,我这么讲,不知道大家能不能理解,能跟上哪个老师扣个一,然后像这些程序写起来就比较简单,你就不用去管这些特别难以调试的bug,这些呢特别难以调试bug呢相对难难以产生。

当然多线程的麻烦就在于,不是说呃你这个指针被别人删掉了,这只是其中一种办法,多线程还在于我们共同访问的时候,数据的不一致性,这个了解过多线程的,应该我一说你就明白啊。

好并不是说他会把所有的这些问题全部解决了,不是这么回事,呃因此呢这些语言一旦诞生之后就开始流行,为什么,因为它开发效率非常高,大大的降低了程序员的门槛,java语言诞生之后很快就流行呃,原来学C的。

学C加加的很多都是转向java了,为什么,因为它简单,在这个方面,起码在这个方面比C和C加加简单得多好嘞,这是这些语言的诞生,当然每一种语言都有它自己的,垃圾回收的内容都不太一样。

我呢在我们的VIP课里讲过,java是怎么样垃圾回收的,讲过go是怎么垃圾回收的,Python相对简单,Python就是使用的这种这种叫叫引用计数啊,它它的算法相对简单嗯,但是讲到这儿呢,我也得朝我们。

我们我们是讲到了现在啊,从过去讲到了现在,现在呢这些语言很流行,但是呢这些语言有很大的问题,他也没有解决什么样的问题呢,就是java空指针的问题依然没有解决,你能保证你传给java的任何一个引用。

它不是空指针吗,很难保证你有一个参数,你接收过来之后,你是不是在java程序里面还得跟那判断判断啥,if你传给我的参数不等于空,怎么怎么办,就说这个你依然不能保证它是不是空指针。

虽然java的有各种各样的什么option啊,什么什么对于空指针的这方面管理的类啊,但是他依然没有解决这个问题,就是野指针的问题依然会存在,野指针问题在java里面依然会存在,Ok。

Python里面go里面我告诉你依然会存在,这是第一个,第二个呢,同学们,你们拿大腿想想看,作为我来说,我只管分配有另外一个人来帮我回收,那么他回收的时候一定会占用CPU的执行时间。

一定会占用CPUCPU资源一定会的,所以它的执行效率相对低,所以我们说java写的程序,Python写的程序,go语言写的程序相对于CC加加来说,你放心,没有人能超过他。

他们的效率在长时间运行的时候一定会低,当然这些语言都自己都自己都会吹牛逼啊,说我java采用了GIT是吧,just in time compiler啊,叫即时编译器,采用了之后呢,我跟C和C加加差不多。

你废话,你采用了之后就就是那么一小段程序和cc下,这差不多好吗,并不是说在比方说我7×24小时,365天不间断运行的这种服务器程序上,你总体算下来,一年算下来和C和C加加的执行效率差不多,不可能好。

第二个呢,Python那就更不提,更不用提了,go语言呢号称啊我是替代C的,所以我的执行效率特别高,我比我比java还高,扯淡,go也有严重的这种垃圾回收器占用的时候,停顿时间叫STW。

就是我垃圾收垃圾收集器开始干活的时候,你其他的线程都得给我停住,生产环境之中,有人遇到过的go语言的垃圾回收,停顿时间长达数个小时,所以大家千万不要迷信一种语言,我呢讲东西呢。

我是喜欢站在架构师的角度讲,我并不偏向某一种语言,但是我需要用某一种语言来落地,最流行的是java,现在呢有一些地方在开始认购,所以呢我有讲价,我有讲go,其实站在一个牛逼架构师的角度来说。

语言呢只是一个工具而已,作为一个结构结构化设计师,哈哈架构是吧,你要盖一座大楼的时候,这个柱子该用水泥,用水泥,这个门该用木头,用木头,然后这个洗手台子该用塑料,用塑料啊,该用化工的其他化工材料。

用化工材料呃,如果从软件角度讲呢,你做你造一个非常非常复杂的软件,你这个地方该用C加加,用C加加,该用Python Python改用够用够,该用rust,用rust,所以我希望大家呢。

在以后你的学习和成长过的历程里头,超越语言,站在一个更高的角度来考虑问题,建立架构师的思维,你的薪水才能够做更高的突破,可以这么说啊,任何一种语言,包括java,包括Python。

你如果只是局限于这些语言的时候,告诉你你的薪水,一线城市目前差不多三五十万到头了,超过这个数的很少,但是如果站在一个架构师的角度,他的薪资会达到多少,120万以上,OK来认可老师这句话,给老师扣个一。

java没学明白,没关系啊,语言这东西呢你就理解为它是一把大砍刀,你学会用斧子砍柴了,下一步你就是用菜刀切肉,如果用菜刀切肉,你学会了下一步,你说用水果刀削水果,你说它很难吗,不难很类似。

需要你就是就是熟练度不同而已,好吧,所以这两类语言叫做有什么特点呢,这类的特点就是它的执行效率非常高,但是他写容易特别容易产生bug,你得手工去管理自己的内存好,这是这类语言,这类语言是什么。

这类语言是它开发效率特别高,但是你管理内存的时候,你你你你你呢他执行效率就会比较低,这个内存的管理上呢,它就会引用另外一个让别人去管,我自己不用管,我省了很多事好,那么有没有一种语言运行效率又特别高。

运行效率超高,对标的是汇编CC加加,不用手工管理内存,没有DC,OK恭喜你啊,现在它已经诞生了,这个语言叫rust,但是他也有他的毛病,学习曲线巨高,Ok,这是run呃,有同学非常的好奇。

说老师这事儿很神奇啊,运行效率特别高,我跟C和C加加差不多,然后你你你只管自己去往内存里头分配,就可以了,你不用管回收没有GC哇,他是怎么做到的呢,rose没听过是吧,你low你太落伍了啊。

你是这行业混的吗,你稍微稍微关注一点最新的技术的发展,大哥希望大家伙的学习叫做与时俱进,嗯这词儿呢非常的重要啊,就是你呢学习上一定要与时俱进,咱们入了这个行业,你要想不学习就能持续不断往前发展。

不可能的,那就是温水煮青蛙,把你自己慢慢煮死,好吧好,大家看这里啊,这个Rest呢是比较新的一个语言,它的特点就在于这,它运行效率超高,和C和C加加差不多,但是开发效率也并不低,原因是什么。

原因是你不用手工去管理内存,你只管去分配就行,你不用管回收牛刀吧,好他主要是怎么做到的呢,你想听吗,今天主要讲JVM的GC的,顺带给大家讲一讲,好吧,来看这里,我我告诉大家一个特别特别特别牛的一个概念。

他特别牛的概念叫什么呢,叫ownership,叫ownership,所有权,所有权的概念,这个所有权的概念是什么意思呢,所有权的概念就是这里面的每一个值。

嗯就是这里面的这个这个,这个这个任何一个值啊,任何一个值都归属于一个变量,就是一个变量代表一个值。

一个变量指向一个值,任何一个值都归属于一个变量,然后有且只有一个,不可能有多个,这句话什么意思,我形象一点解释,我告诉你,在这张图里面我们会有多个变量好,这叫一个变量,O是一个P是一个啊。

这里O是一个P是一个好,有多个变量指向同一个值,或者叫同一个对象,在rust里面这件事情不可能发生,哈哈听懂了吗,我再说一遍,Go on g c,讲讲go on g c。

是接近于java语言里面的ZJC的一种算法,接近于它啊,类似,好大家看这里我再说一遍,重新重复一遍,就是多个变量指向同一个对象,这件事不可能发生,只会发生什么呢,同一时刻只会有一个变量指向这个对象。

这就是所有权的概念,叫做我们这个值的所有者只有一个一夫一妻制,不知道大家听清楚没有,那有同学可能会说了,老师这有什么好处吗,来你们拿大腿想一想,小伙伴们,假如我在占空间。

任何一个战争里面的变量指向的这个空间,如果确保是一夫一妻制的话,那我这个我们叫她丈夫吧,她的丈夫消失的时候,他的妻子是不是顺带的就殉情了,听懂了吗,再说一遍,她的丈夫死掉的时候,什么时候死掉了。

还记得吗,他的妻子就跟着殉情,自动就给你回收了,你发现没有,没理解是吧,听我说还记得占空间里面它的特点是什么,占空间特点是当我这方法结束了,我这占空间就不存在了,我这方法结束了,占空间不存在了。

哎我们假设如果这个P你已经确定它不存在了,同时是一夫一妻一妻制,没有任何其他人指向这个对象,你们好好想想看我这个对象是不是可以回收了,方法结束占空间里变量指向的任何空间,跟着回收就可以了,听懂了吗。

也就是说我不需要DC,为什么不需要DC大哥,你这边你这边消失了,我给你加几行代码,把这个里面关联的编译器帮你自动加的啊,关联的内容OK直接就给你干掉了,所以,这是rust的它的一个核心的设计理念。

rust的这个特点诞生之后啊,同时在堆叠加了它的这种对于多线程访问的呃,共共共共享变量,必须你得你得要采用它特定的书写机制,才能写得出来,它会产生一个特别奇妙的东西,叫做你写不出bug来,好说一下哈。

这是rust语言特别有意思的地方,叫做,不知道的不知道大家听清楚没有,你只要程序的语法能过,就不会有bug,当然他语法非常特殊,这讲着讲着怎么讲成rust了,逻辑bug是任何语言都存在的。

任何程序都躲开了大哥,逻辑bug是啥,你本来让你计算这个程序的一个人的年龄,你给计算计算成为一个人的体重了啊,本来让张三娶了李四,你非得让他娶王五,那这种bug你这跟语言有半毛钱关系吗是吧。

所以这个语言没关系啊,咱们说语言层面的bug,rust呢给你消失,消了很多,除了我刚才说的这个ownership之外,除了还有呢就是在多线程的这种写法,多线程写法叫做固定的,你知道吗,你就得这么玩。

你不这么玩的话,你根本写不出来,你想让多个线程访问同一个值吗,我告诉你,你只有这种写法,你不用这种写法,你根本就写不出来,所以只要你写出来就没bug,就是这么的牛叉,啊我不知道我大概说清楚没有啊。

但是咱们今天还是还是得说回来。

并不是讲rust的,不感兴趣对不感兴算了,反正你们对新的东西也不太感兴趣,我们讲老的吧,讲这边好了,这是语言的发展历史,你要明确这个语言这么多类,还有同学说老师那JS这种东西是什么。

其实这些都是自带垃圾回收器的好吧,就JS这些啊,还有像什么,还有还有想其他的啊,这COLIN等等,这就不说了,它本身就是运行在JVM上的,所以他肯定是带垃圾回收器的啊,还有像什么SCALA。

啊就是老师给你讲东西呢,我希望讲那个层面太低了,我希望你站在更高的角度上来教你认识啊,就整个一个IT界的一个发展,还有呢整个语言上的语言层面上的一些东西,你站在更高的角度上建立起来你的知识体系。

系列 5:P40:40、Spring中的AOP你真的理解吗? - 马士兵学堂 - BV1E34y1w773

18年对应该是那个时候好了,之前呢其实我讲过N多次,spring源码的一些公开课程了,很多同学其实公开课学到了很多东西啊,spring源码在之前授课过程中一直讲的是什么呢,是IOC相关的一个知识。

今天是首次分享,分享一下AOP,讲一下AOP的东西,其实AOP啊,很多同学我之前一直一直为什么一直没讲,原因其实也非常简单,原因在于AOP你要想了解清楚了,必须要把IOC理解清楚。

如果IOC你了解的不清楚的话,永远记住a OP,你是搞不清楚的,明白意思吧,他们俩是一个相互依赖的关系,所以这块你必须要搞清楚,为什么今天讲了哈尔滨一样,IOC讲过很多遍了,很多同学多多少少都听过了。

所以今天来分享一下AOP相关知识,来聊一下UP吧,什么叫AP啊,最简单的一个理解,面向切面编程,面向切面编程,这是它最基本的一个意思,然后呢面向切面编程好吧,它里面在进行实践的时候。

实现的时候一定用了什么机制,同学应该知道叫动态代理吧,在进行动态代理的时候,你需要注意一点,注意什么,它有两种不同的实现方式,一种是CDAB对吧,还有另外一种是a OP的方式,要不是JDK的方式。

两种方式你必须都要知道,大概表达什么样的一个意思,这东西啊说起来很好理解,很多同学可能也都会,但是我想强调的是什么,整个流程你自己有真的穿过吗,你自己有真的感受过这个过程吗,它一步一步是怎么调用的。

我们到底应该如何进行处理,这块面试中也会问问的比较多,同时是大部分同学的一个知识盲区,如果你掌握的话,一定是一个非常好的加分项,所以往这儿好好听,第一个先聊几个概念,叫a OP中的核心概念。

想一下AOP没有什么呀,核心概有哪些,第一个有什么切面,还有呢切点吧,切点还有呢,切入点我们叫连接点吧,对不对,还有呢通知,对吧,还有呢支入,对吧,还有引进等等一堆概念,光看这些名词。

你可能会感觉这东西太难理解了,我压根理解不了,那我们从代码的层面上来说,它到底需要的是什么东西,我们到底应该怎么去解释这块东西,或者说我怎么去理解它,其实记住了它非常简单,不要把它理解得非常难。

所有的技术你认为难的技术都是纸老虎,只不过你没有认真耐下心来,把这东西好好研究一下,先说一下什么叫面向切面编程,这东西怎么理解,举个例子,第一个假如说第一个,我这有一个方法好吧,下面有一个方法。

有三个方法,master1懵逼了是吧,懵逼之后会好好听,听完你就不懵逼了,Max max3,老师这节课VIP有吗,肯定有啊,武器里面讲的比这个更更更详细啊,来往上好好听,首先我有三个方法。

它们归属于不同的类,它指向的是class a,复制一下,它指向class b,下面的指向是class c,这可以吧,三个类里面三个不同的方法,这个方法里面一定包含了自己不错的。

那个很多的一些什么实现逻辑吧,你做增删改查也好,还是做一些CRUD也好,无所谓啊,不管你做什么操作,衣服也好,for循环也好,一定包含了很多逻辑代码,逻辑代码,这时候就有一个问题,什么问题。

当我这三个方法我都完成之后,我现在有这样一个需求,什么需求呢,向往这些方法的,在这些已经写好的方法上,添加一些对应的什么日志,处理工作怎么办,比如说方法前方法后,我分别要进行这些日志处理,我应该怎么做。

正常的一个思路的话,同学们可能想很简单啊,你现在有三个方法了,按照把每一个方法的前面和后面,都加对应的日志处理即可,是不是改方法就行了,我们之前遇到逻辑的时候,一般都是改方法,这个思路没问题。

但是你想一下,现在只有三个方法,三个方法可以自己动手改,如果有100个方法呢,方法的同学老师我也可以动手改,你累不累啊,麻烦吗,对不对,那这时候就要想一件事了,当方法增多之后,修改每一个方法的源代码。

肯定是一种比较低效的方式,说当需要添加逻辑的方法比较多的时候,如果去修改每一个方法的源代码,好吧肯定效率很低,因此在这种情况下考虑一种方式,能不能有一种更好的方式,是按照某种匹配规则去匹配方法。

然后添加对应的日志处理,可以吗。

如果有这样的一个方式,是不是我们想看到的,来我这写的方式,这句话能理解同学扣一不能理解的扣二。

什么方式先不管啊,什么方式你先不用管,我知道了,有一种方式好吧,可以在这个方法里面进行一个切入。

增加对应的一个日志逻辑处理,很明显没问题吧,这个时候问题又来了,每一次我们在手写的时候都是java文件,java文件,Mac java文件,如果想把java文件运行起来。

那意味着所有java文件都要变成字节码文件,你想一下这个字节码文件是已经生成好的,一个写死的东西吧,对于写死的东西,我已经加载到我们当前的JVM里面去了,我还能对它进行相关的修改操作吗,如果想修改的话。

我还能用原生的class文件吗,不懂了吧,因为你要知道java程序想运行的话,他预测的就是我们对应的class文件是不是意思,所以这时候就想了,我能不能由JVM,根据我们当前的逻辑听好这句话啊。

通过某个技术某个技术好吧,在什么程序运行期间好吧,根据需求动态的创建字节码文件,好吧,当然所生成的字节码可以在内存中,也可以写到一,写到一写到磁盘,但是最终要有一个class文件,这可以理解吧。

如果我可以动态的改变我们的class文件的时候,你就想一下在中间处理的时候。

上面class文件不能动,所以呢我动态生成一个新的字节码文件,生成新的字节码文件无所谓,就是添加一些什么16进制的一些字符串吧,把它加进去,加完之后完成我们具体的一个逻辑,如果让你去手动修改。

很明显手动修改麻烦吧,很明显很麻烦,因为你需要对什么,对class文件足够熟练才可以麻烦,那这时候出来了一个新的技术,什么技术叫a s m gun static渠道的,它是一个什么,是一个框架,记住啊。

它是一个框架,你可以搜一下ASM。

啊嗯什么东西来看。

随便一个解释啊,ASM是一个java字节码操控框架,它能够被用来动态生成类,或者增强既有类的功能,SM可以直接产生二进制class文件,也可以在类被加载的时候,JVM虚拟机被动态改变类行为之前进行插入。

是这意思,说白了就一句话,它用来生成我们的class文件,这样能不能理解动态不需要手动了,动态的框架,动态生成,好吧,那这种方式相比较而言的话,它应该是一种比较简单的方式吧。

而至于说ASM怎么生成的,注意如何生成,不需要管,生成不需要管,好吧,目前面试还面不到这个级别,所以这东西对你而言无所谓,无关紧,要,先扔一边,不管它,那既然有这样一个方式的话。

你就想一下,如果我现在不改java文件,我直接去改class文件,我在class文件某个指定的方法的前面或者后面,加上我们的日志处理不就完了吗,是不是意思,正因为有了这样一个技术,所以可以干嘛。

就是这句话再重新生成生成,或者在原来的class,文件基础之上,直接添加日志处理的相关逻辑即可,这句话能理解同学扣一,能理解吗。

可以吧好吧,这就是我们这个面向切面编程。

好吧,就是这个核心的一个机制,用通俗的话给大家解释一下,如果这东西你能理解了。

下面注意了,它起了一个对应的名称叫什么呢,叫a OP,a OP叫面向切面编程,它是一种什么叫编程思想,编程思想,有了思想之后,我必然要有具体的一些实践吧好吧,而如果我想去进行相关的一个实践的时候。

你就要考另外一件事,什么事规范要有吧,什么叫规范,我在实践的时候,我怎么加加什么类,加什么方法,怎么写代码,怎么写,配置文件怎么进行处理,我一定要对应的规范好,或者说有对应的要求。

当我定义好这项要求之后,我只要按照你的规范要求进行实践,是不是就可以完成我们具体的一个功能了,功能什么意思啊,所以注意了,同学们在spring中AOP里面,它其实就是定义了这样一堆的规范。

那这种问题来了,什么规范啊,往里面插代码的时候,往哪儿插,怎么插入,所以他给了一堆什么,我们前面讲过的这些技术名词。

什么切面,什么切点,什么连接点,什么通知。

什么支路,一堆名词看起来很难理解好吧,但是不重要,来我说一下我们需要什么东西。

先想一下,你想往哪一个方法的前面或者后面进行插入,如果我有100个方法,这一版方案里面我想有50个方法,注意啊,我想有50个方法好吧,被进行日志操作,另外50个方法我不需要日志操作,我怎么办。

能听到这句话的意思吗,100个方法有一部分我需要加这个日志操作,但另外一部分我不需要做,我怎么把它给区分开啊。

怎么区分开,最简单的一种区分方式。

我们可以按照类型匹配啊,不是不是类型,我没看到什么东西,按照某一个类别匹配,那这个类别在进行匹配的时候,你很难固定说我的类名就这么起,我的方法名就这么起很难,那这时候怎么办。

我能不能让它遵循一部分的规范,就说我能不能通过一个,类似于与正则表达式的东西来匹配,可以吗,可以吗,所以在spring中,它专门的有一个具体的对象叫什么叫expression。

expression啥玩意儿,你通过翻译应该知道这个名词叫做表达式,是不是意思,你想一下,如果我有表达式之后,我要想进行匹配的话,我应该包含哪些规则,或者包含哪些描述,哪有描述,其实无所谓,就几块。

我们这写一下第一个方法名字你要有,是不是这意思啊,第二个方法的参数要有第三个方法的返回值,你要有吧,这几个东西是不是都要必须写出来,我是不是可以按照我们的名字好吧,参数个数包括返回值的一个类型。

参数的类型,我能不能去进行相关的一个匹配操作,忙还是不忙能吧,包括甚至什么你当前方法所在的完全限定名,什么叫完全系列名啊,报名加类名儿吗,我可以根据包叫类,然后呢来进行一个设定,这都是OK都是OK的吧。

所以第一个对象就已经有了,来这个地方能理解,同学扣一能理解吗,就说我是为了干嘛叫匹配方法,第一个点写过来,匹配方法,匹配方法好了,第一个当匹配方法有了之后,第二个我在方法里面加的时候。

你应该知道一个方法里面不可能只有一行代码,可能包含了N多行的代码对吧,那这时候就想一下,方法的哪些位置可以插入代码呢,说到这个问题,比如方法哪个位置可以插入,你想一下,当我在开始执行方法之前。

最前面能加一个吧,比如最前面可以加一个对吧,然后当我方法的核心逻辑执行完成之后,最后面我后面可以加一个吧,然后再想一下还有什么还有什么东西有前面了,有后面这块啊,都表示了我们的核心逻辑好吧。

核心逻辑还有什么,我出现异常的时候,我是不是可以加,对不对,同样的有些方法是有返回值的,因为方法没有返回值,我在返回值的时候是不是可以加,是不是一共包含了这四种对应的消息通知。

那这四种通知对应过来之后就是啥叫before,是不是意思,然后呢后面还有一个,后面有一个after,对吧,还有一个异常叫after throwing,还有一个返回值叫after returning。

是不是玩意儿,我是不是有了这些对应消息通知了,为啥异常时候能将你在一出现异常的时候,我们怎么处理来着,我们一般情况下在进行异常处理的时候,都是try r y括号,大括号。

然后呢后面可以跟一个什么catch对吧,大括号后面可以跟一个什么叫finally,我们一般是不都都这么写的,那你告诉我,我catch里面我不能做一些异常处理吗,如果我就想说,如果出现异常。

我加一个日处理,你怎么办,你是我开指定加了,那我是不是可以指定,我们对应异常的一个情况了,专门在异常的时候进行使用,是不是意思,这也能理解啊,这个同学叫没名字啊,你这东西你应该能理解啊。

专门为异常所准备的一种情况,因为代码出现异常是一种正常情况。

你代码如果不出bug了,反而不正常,明白意思吧,当我有了这四种之后,你就开始想了,大部分情景里面我们一般都是怎么样,前面和后面是不是都要加,每次都写两个,可能太麻烦了,所以在他们两个的基础之上。

基础之上,我可以这样再加另外一个额外的东西,叫什么叫环绕通知,环绕通知就是我们说的around,既包含前又包含后,什么意思啊,既有钱又有后对吧,一共在spring中提供了这五种对应的通知类型,通知类型。

这能理解吗,所谓的after也好,before也好,还是after throwing也好,after returning也好,around也好,他们表示什么意思,他没有什么意思,我们虽然说了叫通知。

对不对,给个名词叫通知,叫通知,但是你要注意一点了,当前这个通知有了之后好,我要干嘛,这些before after after throwing after return,里面是否包含处理逻辑对吧。

包含,哪怕你就打印最简单的一句话,打印什么话,比如说写这样的话,The system,点out点print line,写一句话叫方法开始执行,这句话是不是也是一个逻辑处理。

我是不是要把这些before after after returning,After throwing,我都变成类似于这样的一个描述,他是不是有方法了,是不是有方法,那这些方法叫什么,这些方法叫什么。

给个名词,什么名词啊,叫啥,别光送花,听课好,听课好吧,不让送花了,叫什么切面吗,a OP吗,好了,这给了一个名词,同学们需要记住了,叫什么叫advice。

刚才也给出了通知。

系列 5:P41:41、AOP的几个核心概念 - 马士兵学堂 - BV1E34y1w773

刚才说叫切入点,切入点放这可能那个名词不太合适啊,就叫消息通知advice,翻译过来叫通知,其实也不太合适啊,你就知道了,它是包含某个具体处理逻辑的,而一般情况下我们在写的时候可能包含前置,包含后置。

包含throwing,包含RETURING,这些东西可能都包含在里面去,当我都包含到里面去之后,这些东西能不能给一个统一的规范的一个描述,或者说放到某一个对应的切面里面去啊,放某一个固定地方。

这里加个背景,当我定义好我们确定的这些具体的通知之后,它里面都有具体的一个方法处理逻辑了,我能不能把它放到里面去,那放到这些里面去之后,它称之为什么,这东西称之为什么玩意儿,切面吧。

是切面叫as pet,要有当前那个切面,当我有了AOP了啊,当我有了这个匹配方法了,当我有了这些切面,有了这些advice通知了,其实我就可以完成什么完成,AOP的过程了,或者说完成。

面向切面编程的所有操作,我只需要知道这几个对象就可以了,但是我们应该知道,当你定义好通知之后,这些通知可能是同时存在的,当这些所有通知都同时存在之后,我一定要有一个什么具体的执行顺序吧。

我不能说谁想先执行就先执行,谁后想后执行就后执行,这肯定不行吧,那当我有这样一个顺序之后怎么办,而且你发现了before也好,after也好,around也好,throwing也好,return也好。

它们应该是包含自己指定的顺序的,而且有可能本身就是有什么嵌套了吧,比如说我先执行before的方法,当我执行完比方法之后,我发现了里面有一个around,我是不是可以执行,或者执行完之后。

我能不能再加一个before都可以吧,它有一个嵌套的过程,而这个嵌套过程,每一个通知你最终都是要执行的,因此基于这个维度考虑什么事儿,可以考虑什么事,同学们在spring a OP中。

它引入了一个非常核心的概念,叫什么叫责任链模式,什么叫责任链模式,谁能解释一下吗,这玩意怎么理解,啊怎么理解啥叫责任链,你们都接触过,往下看,有人接触过滤器吗,接触过吧,啥意思啊。

假如说我这里面有一堆通知,这是advice1,举个例子啊,advice1这个advice啧,那V2有三好吧,有四家有这堆这一段执行的时候,当你执行完成之后,最终的才是谁,我们具体的核心记住叫核心逻辑。

是不是意思,所以我整体的一个调工程变成什么样子了,从刚开始第一层,从第一层开始,从这儿来往下掉掉下来,第二层掉下来,第三层掉下来,在这块当我调完成之后,最终会调到我们的核心逻辑里面去,当这执行完了之后。

没完还要干嘛,还要把当前的结果给返回回去,你不能说没有返回吗,肯定要有返回的,再返回去返回,这是一样的,返回返回,是不是这意思,我必须要有这样一个返回的过程,这东西就可以称之为责任链。

而且在中间某个调用过程中,我再接着往下调,再调用的时候,后面这块逻辑可能还没执行完,我改下名字二,然后三然后四,这都能理解吗,来这个图能理解,同学给老师扣一过滤器,是用这样一个方式对吧,这也是一样的。

一模一样东西,我就是挨个往下进行相关的一个调用,当我调用完成之后好吧,下面来再接着聊聊啥,有当前链了,我要去拦截我们对应的一个方法好吧,那我在方法拦截的时候,我需要怎么拦截啊,我怎么去调用当前方法。

其实这里面还引入了另外一个机制,什么机制,正常情况下我们的代码怎么执行的,从上往下依次执行,假如说我想在中间某个环节执行过程中,当你到这个环节之后,我要执行其他的一些额外逻辑,怎么办,额外逻辑我怎么办。

这还用什么样的一个机制,什么样的机制没问题啊,正常情况下代码是往下执行的,这是我们具体代码逻辑,但是在中间某个环节的时候,我想让它在执行一些其他的额外逻辑,或者怎么做好了,同学调节点叫观察者模式。

模式观察这个模式它最本质的东西,它是一种什么回不是设计模式啊,什么机制啊,它是一种什么机制,同学们,总代理事件扔开扔开观察者模式好不好,好了,对监听我不提供这种模式了啊,这个这个这个例子举的不太好啊。

这不太好,共和纸什么东西呢,想说的是啥,想说的是回调,这样一个机制叫回调机制,这回调你必须能理解什么叫回调,本来我传递参数的时候,我没做任何的一个执行,到后面执行某个环境接的时候。

我可以再把刚刚传进的方法进行一个执行啊,对类似于钩子函数和回调这样的一个方式,而我们在进行回调的时候,在我们具体的spring源码中好吧,它提供了一个非常核心且巨化的类,什么类。

就好比你们之前写代码的时候,一定见过几个对象,什么对象来,有没有见过这样的东西,第一个叫method interceptor,你见过这东西吗,见过吧,除了这个东西,如果你用的是纯原生的JDK的话。

你有没有见过什么东西叫invocation handler,见过没,JDK动态代理的时候,你一定见过这玩意儿,JDK是不是这意思啊,动动态JK动态代理,代理你一定用过这套机制。

同样的它里面有一个method interceptor,在我们整个spring的框架源码里面,它也提供了类似于这样的一些描述,只不过它里面包含的比我们了解,要多发什么东西来往下看,有这样一个对象。

你看一下叫call back,In f,没有啊,call back写错了吗,好往下看往下拖,拖拖拖拖拖到下面,这东西叫cubs,里面包含什么东西,每一个call back的对象有什么东西。

none NO o p好吧,有什么呢,叫method intercepor,这东西我们见过对吧,还包含什么叫invocation handler,我是不是也见过。

在包含后面还有什么什么lazy load对吧,还有什么叫dispatch,后面呢还有叫fied value对吧,后面还有一个叫propose r e f dispatch,是不含这么多类型。

这类型啊我们一般都接触不到,但是在经常使用的时候。

一般这样东西用得非常多,就是说当你的方法想要具体被执行的时候,被执行的时候需要啊,这么这么这么写不太对啊,什么意思呢,通知,通知需要想要被执行,到时候好吧,需要进行相关的拦截好吧。

需要什么叫实现method interceptor接口,这个东西怎么理解,我刚刚说了吗,你想一下,这是我们刚刚的方法逻辑,正常情况下,假如说我先调method1,调完master1之后。

我调method2,调完method2之后,我调method3,它正常情况下是顺序接着往下走的,一个掉一个,这个时候你想在方法一前面加一个逻辑方法二,一下面加一个逻辑,方法二,前面加一个逻辑方法二。

后面加一个逻辑,你这是不是相当于把整个调用链给拦截掉了,这能理解吗,无理说MBC连接器可以这么理解,是不是可以把它理解为一个拦截器的链,当我有了DJ之后,我是不是可以把当前代码的一个。

正常执行顺序给拦截掉,这能理解吗,还能理解同学给老师扣一,能不能理解,而那些拦截器在进行具体代码实现的时候,这就相当于是我们的advice,所以你会看到你的advice里面。

有些是需要实现method interceptor的,来举个例子吧,找一个比如说有什么叫嗯,你点不过来啊,看着啊,它具体时间类,比如说叫as pet,挨着看吧,Before method。

Before b e f o r e o r e advice,完了看它有实现我们具体的method inside inception吗,没有吧,来再看另外一个aspect对,然后呢。

after advice他有没有实现,他实现了没实现了吧好吧,你能看到这个接口啊,这个AVS通知实现了当前这个method接口,但现在,那你。

你信啊,谁天天吃饭,谁是小狗,可以吧,这是不是可以没顾上啊,不聊这事了好吧,一会再说啊,再说啊,来好,这节课,我们想在进行具体的当前这个执行过程的时候,怎么执行啊,第一步干嘛,第一步干嘛。

同学们永远别忘了一件事,别永远别忘了一件事,什么事,spring虽然是个框架,同时它是一个生态,但我们在更多描述的时候把它称之为什么,它是一个容器吧,叫spring容器,我是IOC容器吧,这么说吧。

IC容器,那容器意味着什么事,在容器中一定存放对象吧,但是我要先有容器吧,所以第一步能不能说出这样一句话,什么东西叫做先准备好吧,存放对象等容器可以吧,这可以称之为我们的第一步骤。

当这个步骤执行完成之后,容器有了下一步干嘛,下边干嘛,想一下,容器是第一个环节,我把容器先准备好,当我把容器准备好了之后,第二步要干嘛好了,放东西,非常对,叫存放具体的对象,但在存放之前你要干嘛。

是不是要进行对象的实例化和初始化操作,将生成的完整对象好吧,放到具体的啊,放到容器中,容器中,这没问题吧,这是第二步,当你的容器都准备好了之后,第三步在干嘛,现在干嘛,是不是要从已经创建好的对象啊。

容器中好吧,获取需要的对象,然后呢再往下一步,干什么,这叫调用具体的方法开始。

进行登录是不是过程。

系列 5:P42:42、图解说明AOP的运行流程 - 马士兵学堂 - BV1E34y1w773

有这样一个对象,意味着我要往当前对象里面放chain,是不是这意思,所以它在进行最调用的时候是怎么调用的。

外面有一个包装好的衬对象,对象对象好吧,这东西它需要什么,我第一次调用的时候,通过chain对象里面好吧,我取出0号位置的元素,然后呢再进行第一次调用,到这是第一次,当它调用完成之后,我需要干嘛。

我需要干嘛,同学们注意了,当你这调用完成之后,我需要调下一个,对不对,当我调下一个的时候,我要知道我下一个是啥,我怎么知道我下一个是啥,没问题啊,我怎么知道我下一个是谁,你知道吗。

不知道你如果不知道的话,就意味着你当前这条路线,你要回到当前这个chain的链条里面,我是不是才能找回来,所以第二个从这儿回来来,这东西能不能理解,他是不是回来了回来了,回来之后好了。

我刚刚取的是下标为零的元素,下面我该选谁了,想要为一的元素吧,那如果唯一的话,我要取到这块,这是二第二个步骤对吧,那这是第三个步骤,能不能理解,能理解吗,同学们,这个路能理解不,哎这个比较麻烦的地方。

可以吧,那一样的,我调完它之后,我依然要返回回去,往上走,这是第四个,回来之后我再要怎么样呢,从哪找,第三个,这是第五条路对吧,然后呢再接着回去,往往下拉距大一点,往下走,这是第六个对吧。

他进来之后一样,我再找下一个,这是第七个,他回来之后我一样,他也要返回返回去,这是第八条路,往回走没问题吧,这是第七,然后呢当你做完之后,下午再来吧,我从这儿画了啊,这再来,只要大,这是第九个对吧。

这时候这是第十个,来当前这个调用过程能看明白,同学扣一没问题吧,对这个调查过程应该还是比较清楚的,比较比较好理解的,那这时候你就想意味着我在整体的调研过程中,我必须要时刻知道当前这个对象吧。

而且我在任何一个around也好,before也好,after也好也好也好,我里面必须要能够获取到当前的性对象,什么意思啊,因为你不获取到充电桩的话,我是不知道我从下一个链开始往哪进行调用的。

我找不到了,是不是这意思,所以他给当前这个链式,这个结构也包装了一个对象,换什么东西,它的名字也很好玩,什么意思叫看好了啊,叫什么叫expose invocation,Interceptor。

这东西他给了这样的一个名字,但他给的名字叫什么,叫暴露的执行拦截器,它本身也作为了一个什么东西,叫advice,看这意思吗,本身也作为一个advice,而在进行调用的时候,它是谁,他是第一个被执行的。

也就是说在这个执行过程之前,还有一个什么叫0号位置,0号位置来看一下我们是不是这样一段过程,来,我们走下这个走,走下这个这个过程,分列式给值必须要返回吗,什么叫给值必须要返回,没听懂啊。

1+7这个图如果你能明白的话,下面该干嘛了,我是不是要挨个进行相关的一个调用了,先问一下第零个我指向哪个元素,没问题啊,第零个我指向谁,Come on。

这叫exposed invocation interceptor,因此我们刚刚看到这个链条之后。

你发现了这个链有几个元素六个吗,第一个叫什么叫invoke,叫expose invoke interceptor,最后第一个取的因是它怎么取得,看效果很好玩。

走我创建一个对象叫CD lib method invocation,创建对象,当我创建好对象之后,好吧,我调了一个什么叫proceed方法,点进去看一下这个方法里面有没有proceed。

proceed调的是谁啊,叫super super,找谁找父类了吧,点开它的父类,父类里面有个什么啊,找proceed,从这开始吧,所以我们最终能进到这块来进去看看吧,好吧,我看你们始终是蒙的啊。

进来来点F7进去,你看一下是本类的吧,当你一进到本类之后,他告诉你说好了,你要叫super调父类了,我再给F7调到分类了,你看一下这个变量好玩不好玩,第一个叫什么。

叫current interceptor index,第二叫interceptor and dynamic method measures,它有几个等于几,它几个等于几个,它的这个结构值一共是六。

他是谁,一吧,为什么一啊,因为我们说了嘛,刚开始取的时候从零开始取,我默认的初始值等于一,好看,默认初始值等于一,所以我在开始获取的时候,判断你第一个值减一等于几,等于五吧,因为你的下标位置是多少。

长度是六,下巴位置是012345吗,是不是这意思,所以刚刚进的时候他能进来吗,这个衣服能不能进来,肯定进不来嘛,你一怎么会等于五呢,肯定进不来,因此它跳过去,跳完之后,你看一下他从这个链里面开始取了。

取的是谁,取的是谁,叫this current intercept index,先加加编辑了,他本来是一,加完成之后变成几个零吧,所以我取出对象是谁。

往下看是不是叫disposed invocation interceptor,我把它取出来,当我把它取出来之后,我要进行调用,执行了,往下走到最后一行进行一个类型转换,转换完成之后。

点invoke开始调用,点F7进去,你看一下他干了什么事,同学们注意啊,这很这样很好玩,这样很好玩。

我说了,我们刚调用的时候,我必须要保证我的每一个通知,每一个通知我都能够得到这个亲对象好吧,而我们的chain对象放到哪了,问一下当前的chain对象,我放到哪个对象里面去了,哪个对象,expose吗。

是0号吗。

哎呀这是白看了,来回来找一下,放哪了,是不是这玩意儿叫CD live method education。

是不是这样一个对象,我放到这里面去了好吧,这里面是包含我们当前的chain,能看到吧,所以当我在进行调用的时候。

你注意一个核心的点,他进去之后往上走,再往上走,当我调super之后,我传递的是谁,this吧,当前的this,你告诉我指的是哪个对象,这是哪个对象,哪个是不是我外面写这个叫CD lip method。

Invocation,对象,是不是他,我为啥要有他呀,我有它最主要的目的,不就是为了获取到我们的吃对象吗,我要知道我下一个元素,或者说下一个通知应该是哪一个吗,我必须要知道他。

因为我只知道他之后我才能理解这是怎么回事,能听懂吗,能听懂吗,那这样能听懂,同学扣一好了,我把放进去。

这放完之后,你们你们你再往再接着往下看,往下看,这get一下有一个invocation,它是什么,一个sweet local的当前线程,那个所共享的sy local把它放进去,放完之后,set是mi。

就我们的对象把它放进去,放完之后开始执行mi点proceed mi是谁啊,就刚看那个reflective method education吗,所以点M7进来。

前中后调的是c live a OP policy,然后再往里边点到这了吧,刚刚我取的是哪个对象,同学们,刚刚我取的是哪个对象,0号吧现在该选哪个了。

一号对不对,往下走往下走往下走,当你获取完成之后,你发现了你获取到哪个对象叫peg around,我们看这零是不是around,是这样的吧,我找到第一个around,当我找到第一个around之后好吧。

我再接着往下走走,开始点invoke,看这个类它属于哪个类,往上看它属于哪一类,as pad j around advice吧,勇敢这设计有问题啊,我靠胆真肥,你敢说他设计有问题。

你还没体会到他那好好好好在什么地方好吧,是不是到这里面去了,上来之后往里面走走走走,准备一堆对象,准备对象之后执行谁叫invoke advice method,是不是它我再点F7进去,再点它进去啊。

往上看再点它再进去处理逻辑吗,好吧,进来之后上面有一堆的参数,判断最终会叫谁叫this as peg advice method,Invoke,他指的是谁啊。

是不是我们刚刚指定好那个around那个方法,不调run方法了,来往这看啊,再接着往下看,我点invoke,点MC进去,进来之后往下走往下走,往下走往下走,往下走,进来好吧,再进去好吧,再往下走进去。

你看一下他找到哪个方法了,谁,我用什么注解标识的,什么注解标识的around吧,环绕通知好吧,这是我们第一个好了,当我知道了around之后,下一个该调谁啊,同学们,我问一下,下一个该叫谁了。

表表示什么意思,before吧,Before,我问一下,当前程序里面有任何跟before相关的东西吗,没问题啊,当前程序里面有任何跟before相关的东西吗,没有啊,你没看到before吗。

如果没有before的话,你想一下before在我们的链上放着呢,那意味着我还要回调到哪,回调到当前这个链上面,是不是去进行找下一个。

所以我怎么调用呢,你看到一个同名的方法叫什么,往下走往下走,往下走,往走走到这步叫PKP点proceed,看到proceed吗,Proceed,你往里边一点击,往下走好吧,然后呢往下走再往下走。

这有一个proceed点,它回到哪了,叫super点proceed吧,一回到super点proceed,你知道了他这个super点回到这个super proceed里面,干什么事干什么事,干什么事。

找下一个吧,是不是加了点F7进去,我又回到这块了,回来了之后,我该取消了AD等于刚刚是一嘛,现在该二了吧,我取到谁,是不是该取到我们的before了,我到before之后再往下执行,再定义VOKE。

进来之后再执行advice before,开始调before自己的方法了,点它继续进来之后,点它好,进去之后点它同名的方法都是往下走,往下走好吧,往下走点1mo,点完之后往下走,往下走,往下走,往下走。

点它进来再往下走,进来到哪个方法了,到哪了,同学们是进到比方了吗,是进到比方了,是进到比方了,当我进到before之后,意味着我可以执行我们before的一个处理逻辑了,对吧,执行完执行完执行完。

我执行完成之后,我还需要干嘛。

我说了,我刚刚是进到around,然后呢回去找before,找完before之后,我要在干嘛,再回去吧。

我要再回到池里面,是不是找这找我们对应的来,往下走好,返回返回都刚刚逻辑返回好,返回返回好吧,你看一下,这是我们的before advice before vice。

当我指定好before vice之后,下一步叫mi点proceed,我一点mi点proceed mi是谁,是不是还是那个CD吧,max有vocation对象,那这时候怎么办,我再点下去吧,点进去之后哇。

又到super了,我再取谁,我再取谁,三吧,点不进去好吧,找找找该谁了,该after除了执行完了,当我执行完之后,点进去叫mi点proceed,又回去了吧,是在之后执行的,我们那个I的方法。

到现在为止我有执行过吗,我有执行过吗,有没有执行过,没有嘛,所以这个后置吗,后置就前一次来进行相关的一个执行啊,前一次要进行相关的一个执行,所以这要进行N多次的一个重复。

那我再回去再调,我再回去再调用,不就完成了我们这样一个链式结构吗,勇敢地再问一个问题,说为什么,为什么要回到好吧,链上直接在代码中进行调用,不行吗,对吧,我就规定好了,我就规定好了。

什么after不是around好吧,那下一个就是before,执行完成之后,我再指向after好吧,我再指向after throwing,我在指向after after returning,这样行吗。

勇敢这行吗,我规定好,每次都这么干,我只要调到around,我就叫before done before,之后直接调after行啊。

来看看东西,我把单代码停掉,停掉停掉好吧,停完停完之后看一个东西,刚刚那你们看是注解的配置,对不对,下面来看一个XML文件的配置,打开我们的AOP的XML文件,配置方式只是换了而已。

你往下看我的执行顺序是什么,注意啊,看执行顺序,看执行顺序,我第一个执行啥来着,around对不对,好了,我把顺序调一下,第一个是around调上去,第二个是before,第三个是after。

第四个是after retention,下1after throwing,跟我们刚刚注解定义好的顺序一样,不一样一样吗,同学们看好问题啊,跟刚刚注解定义的顺序一样不一样,勇敢一样吗。

就为了把你这个劲儿一样吧,一模一样好吧,一模一样来,我再打开我们的测试类,得到我的test好test之后,我这打一个断点,一样的好吧,点F7,第八个重新开始跑,注意看,看什么,看下那个链。

一会儿你就看到了,我问一下,你觉得那个形成链的顺序,跟我们刚开始形成链的顺序一样吗,来试试好吧,一样对吧,不一样嗯,有说一样的,有时候不一样了,我们不吵了好吧,我们用实践来证明它到底一样不一样。

我这个每次都要编译啊,他这个是源码编译,所以运行起来比较慢一点,写反了,最后俩是不是是不是after after return after throwing吗,我刚刚定义那个配置类的时候。

这个顺序不也是after return after throwing吗,没没错啊,来往下看看好了啊,第一步先获取到一个动态代理对象,没问题吧,注解里写了order,插板里面没写,一会儿把它给去掉。

把order给去掉好吧,又把order给去掉,先先先先证这个结论好吧,点F7进去。

系列 5:P43:43、AOP中的拦截器链是如何调用的? - 马士兵学堂 - BV1E34y1w773

接完之后往下走往下走。

往下走,往下走,往下走,往下走,往下走往下走,我们获取链了,你来看一下当前这列的顺序是什么顺序,什么顺序,一样吗,不一样吧,刘老师不对,你刚刚不对。

你刚刚那个呃,我要把这个结果留下来,把结果留下来好吧,放一边,老师,你刚刚在写那个注解的时候,你的那个什么指定了一个at order,我这写的1234来,我把order干掉,干掉把他也干掉,把他也干掉。

把他也干掉,把他也干掉,可以吧,可以干吗,完全没问题吧。

当我把它给干掉之后好吧,我再重新运行我们当前注解程序,我把这个先删除一遍啊,是谁的,这是什么东西,这是我们用在XML文件方式的时候进行配置的,放到一边诶,诶怎么不了了,哎呀完蛋好了,不管了。

反正你们知道它是什么东西,行了,来,我重新启动,把这个也启动一下,右击debug,重新启动,话看好了,这个是注解的吧,你再来看顺序好吧,再看顺序,大家一直以为你们以为的是对的好吧。

但其实你们以为的是不对的,我再问一个问题啊,同学们那个around和before谁先执行,谁后执行影响大吗,没问题啊,around谁先执行和谁和执行一样,影响大吗,不大吧,好来往下走啊,先往下走。

第一步还是一样,先获取到我们当前的拦截对象,好吧,再点F7点ADD进去。

进来之后,进去之后往下走,往下走,往下走,往下走,往下走,往下走,往下走,往下走,来看一下当前的chain,它的顺序什么顺序,我把order已经去掉了好吧,我把order已经去掉了。

order已经去掉了什么东西,Around before after after returning,After throwing,跟刚刚顺序一样吗,这是注解的顺序吧。

来把它拿过来。

这是注解所对应的顺序好吧,然后呢我们再回过头来打开它,嗯怎么看不到了,算了看不到了,跟刚刚我们的配置配置方式,配置文件方式一样吗,跟配置文件的方式一样吗,同学们,不一样吧,代码里写死的,不可能。

他为什么要回到这个链式结构里面,因为每次你在进行这个排序操作的时候,它的顺序是不一样的,那这个顺序是什么来决定的呀,什么来决定的,注意了,在这里面有一个代码,往上看。

这里面有这样的一个方法叫short adviser,什么叫short advisor,什么叫烧脑的排序,是不是对我们的advice进行排序,好吧,当你在进行排序的时候,这个步骤里面会把所有序都排掉。

但是你注意了,他会先把你取到的advisor值,都转成一个这个对象,啥玩意儿不认识啊,不认识,往上点,这上面有这样一个注释,你告诉我是干嘛的,谁能翻译一下。

This class employment a part of order,好部分的排序对吧,实现了一部分排序好吧,it includes ring for doing啊,这玩意谁能翻译一下什么意思。

什么叫top short,顶级排序,你这个翻译还真牛逼,来看好诶,咱们有没有啊。

我也不跟你犟好吧,他叫什么,叫拓扑排序吧,是不是拓扑排序叫拓扑排序,如果是拓扑排序的话,拓扑排序的话,我想问一下拓扑排序每一次的结果是一样的吗。

是这样吗,不一样吧,是不一样,比如说ABCDA指向BA指向C,B指向D。

C指向D,这画不太好啊,我来看这是A,这是B,这是C,这是DA指向了BA指向了C,B指向DC指向D,他们有几个结果,A b c d,或者什么东西ACBD吧,这这这能理解吗,这东西啊,谁要不理解。

去看左神的算法课,左神讲了吧,是不是讲过这东西了,是讲这东西了,你把这个东西如果看明白的话好了,你想一下,我每次能规定好我们对应的一个顺序吗,特别是around和before之间,我刚才问了个问题。

我说around和before谁先执行,谁后执行有意义,有影响吗,没印象吧,如果你采用硬编码的方式把这东西写死了,我这个排序的价值在哪,我不要排序了,我都按这个顺序执行行了,是这样的吗。

你既然具备了排序这个功能,就意味着你是为了支撑更灵活的一个体现,我再举个例子,如果我自定义了没问题啊,如果我自定义了一个the vice怎么办,假如说我既包含在里面用的,我又自定义了一个。

你告诉我顺序什么样子的,能自定义吗,哎同学们能不能自定义,我不是说不是说自行顺序啊,我自定义一个消息通知能不能,我自定义一个消息通知可以吗,先说这个操作,我可不可以自定义消息通知,这可以吧。

如果你自定义一个,你按这个顺序执行,你告诉我怎么办,这个硬编码还行吗,勇敢,硬编码还行吗,不行了吧,所以我为什么每次要回到量上,为什么要回到量上,我回到链上,保证的问题就在于说。

我每次能从当前这个链结构里面,拿到我们最新的排好序的,一个下一个结构的数据,我拿到下一个结构数据之后,我就可以进行调用了,这个链不会乱,还按照我们之前的结构往下走,明白了吗,这能听明白意思吗。

能听明白的,扣个一,所以这个东西存在的意义好吧,每次排序都不一样吗,你在传入相同的一个配置项的时候。

它的顺序是一样的,什么意思,当前代码你不管排重启多少次,当前代码你不管重重启多少次,它的顺序是一样的,但如果你调整了你对应的一些消息通知,包括你如果包含了自定义通知,这个时候就不一样了。

这时候就不一样了,我们这个例子举的比较极端,为什么我里面既包含了around,又包含了before,又包含了after after return after throwing,你在工作中你会都用吗。

Before after returning after throwing,你是不是可以选几个来用,你会多用吗,不会的,所以我只要保证你当前按照这个结构来运行,不就完了吗。

是不是意思,很多老师,那我这样,我把当前这个性对象,我放到每一个消息通知里面可以吗,没问题啊,我把当前的chain对象放到每一个消息通知里面,行不行,行吗,如果你把当前这个链结构放到这些通知里面。

我怎么知道我下一次该取哪一个了,我根据我的名字去做一个判断好吗,我是我是around好了,我取到around的位置,我取下一个位置,我取到了before,我知道before是啥了,我给你放下一个位置。

往里边放可以吗,而且你注意一件事,如果你当前around before after returning after throwing,你都包含了这样的对象,为什么不能把它拿到外边去呢。

为什么不拿到里面去,拿到外边去,本身你相同的东西,我们一直说封装封装封装相同的东西,你就要进封装,你为什么不能把它拿出来呢,明白意思吧,我把它拿出来是一种更好的方式,其他方式并不是说我就一定不行。

我就一定不行,不一定不行,你可以这么解决啊,但是有更好的方式,我们要选择更好的方式来进行相关的一个实践,来相关的一个实现,这次,拿出来就像每次回拿回出来,就像每次回来回来又怎么样了。

你回来会造成什么额外的成本吗,你最终流转是不是也是这个当前的chain对象,而且每次每次回来不消耗性能,你每次比较不消耗性能吗,你每次取集合里面元素不消耗性能吗,我举个例子。

假如说你现在假如你现在有100个通知,100通知你提高到第99个了,还有第100个,你从第零个位置开始挨个匹配,匹配到99个,你怎么知道它下边是谁,能知道吗,这个就不要考虑这个性能方面影响了,好吧。

他就是一行代码执行效率更快的,他这个放到外面之后,它更加独立,更加灵活,好吧,所以这一定要注意了,不要去抬这个杠没有意义好吧,我刚解释半天,这东西真的我觉得意义不大,意义不大好吧。

这个是不是每次回调chain这东西,注意啊,你每次回到chain这个链上,最主要不做做的事情是什么事,是为了找到下一个我要具体执行的哪个通知,到底是啥,到底是啥,谁来做这件事情好。

它在整个过程中维系了各个链的一个组成部分,各链的一个组成部组成部分好吧,这东西啊你要去面试聊的,面试聊的OK好了,不聊这事了啊,不聊这事了好吧,你要去抬这个杠,我也我也我也我也没啥办法。

别别别别别太抬杠没意义好吧,OK对,回来之后,我要找到我下一个集合。

要执行的具体的一个元素值,就这意思好吧好了,把它停掉了,停掉了,这个停掉,调完之后来回到我们代码里面,我刚刚没跑完啊,我重新跑啊,刚被打断了,我们重新跑啊,该下班了,面试都这么难吗,那不会啊。

面试不会问这东西的,记住一点,这东西咱们讲课的时候会会问呃,会会会会会讲这些东西,但这半年工作的时候,一般AOP,如果你能把这个链的一个调用过程,给大家说清楚。

就很草的画这样一个图,我觉得他都会对你有一个新的认知,因为你只有看过源码之后,你才会这么去看它,还要把这个图画出来,如果你不看源码的话。

这东西你是画不出来的,明白意思吧,就这一点注意了,OK来接着往下走啊。

早点ADD来,往下走,往下走往下走,往下走走走走走走走点proceed好吧,一直往下走,注意了它挨个从集合里面取我们对应的元素,取完元素之后,我开始进行调用的一个执行好吧,回来回来往下走,往下走进去。

Model invoke,点它点它进来之后,点它回来,回来回来,我们再往下走啊,往回走往回走,到这执行完了吗,我刚点错了,终于回来了,我刚点错了啊,这个这个哎麻烦了,我刚点错了,所以都回来了。

所以都回来了,我们往里点了3月,反正你知道一点,他有了当前这样一个链条过程之后,是不是能解决这个问题了,来这个这个链条,这个过程能看明白的同学在扣一能不能看懂,好了,当你把它看懂之后。

我们来思考另外一件事,另外一件事,刚刚那个具体的细节调用过程,你下一看,我不带你们看了,它的AOP就这么就这么调用的,就这么调用的好,我想问的是另外一个问题,听好了,这个问题才是锻炼内功修为的,如果。

看好了,如果要自己通过AOP的方式好吧,来实现某个统一的功能,我们应该怎么做,就比如说声明式事务,它是怎么实现的啊,刚刚动态生成代理生成的classmate,那时候自己生成就行了,勇敢你不是VIP吗。

我VIP架构师五期里面我就跟你们说呢。

我刚刚看了一节课,好吧,在架构师五期里面,我纯讲的都是spring源码,好吧,往下翻翻翻哪去了,看这叫a OP拦截器链的一个执行,把这节课看了好吧,明白了吗,把这个看了,勇敢好好去看这节课。

我建议你从前往后看光spring源码,讲到现在我还没讲完,讲了28节课了,讲28节课了,东西很多,100 257很有价值,我希望你能看一下,我是一行一行带debug的,你们其实已经发现了。

我在这里面都有注释,都是我自己加的中文注释,下周我会看好吧,实际的时候啥时候掉,本身来,我们先挨个回答,先先先回答个问题啊,宋祥坤好吧,包括橘子郎都问了一个问题,他说实际的时候什么时候调用本身的方法来。

回过头来回到我们这个链上,在当前这些方法执行的时候,你觉得哪一个通知完成之后,我就可以调用本身的方法了,没问题啊,哪个通知执行完成之后,我就可以执行本身的方法了,你觉得听动捕捉before相当有意见吗。

before吧,是不是这块在这块的时候我可以调动自身逻辑,是不是这块,所以你要想看这东西的时候怎么办。

我再带你们走一遍好吧,哎我这人就是心善,再带你们走一遍吧,好看啊,我这次点慢点,刚刚太快了,所以跳过去了,让大家看到具体调用自己方法的过程,一定会掉的,百分之百会掉,好吧,来走一下吧,啊稍等啊嗯。

连上我找你找到这儿了,我咋有问题啊,我在上课没法回消息,慢慢走,第一步点ADD好吧,进来之后先找到我们对应一个链式结构好吧,然后呢往下走,开始进行执行proceed,然后点super开始取。

先取第一个是谁来着,第一个是谁,expose吧,记住啊,第一个是expose,把它给记住,然后呢开始调用调用执行,调完之后往里面设置一个参数回来好吧,点回来开取第二个,第二个是谁,第二个是谁。

around吧,是不是around好吧,所以我往下走再调用around里面具体方法,往下走往下走往下走往下走,Invoke advice method,进来之后检查再进去,往下走,往下走,往下走。

点invoke,进去进去之后再往下走,点invoke,进来之后再点invoke,invoke好吧,往下走往下走,往下走到这步,proceed再回来,往下走好点,proceed又回去吧,该该该该取谁的。

看见谁了,before吧,好了该before了,再点往下走,进去进去之后先执行before里面的方法吧,是不是执行方面的方法好吧,来点F7进来进来之后,我先执行这里面的消息通知,点进去好,执行完好吧。

这完成之后叫m d proceed,进去进来之后叫super proceed,当你这执行完成之后,我想问一下这个值等于几,等于二吧,是不是等于二,等于二的话往下走,他又进不来,这时候我选第三个。

我取三个取的谁,觉得谁,after吧,哎不对啊,老师没有调用那个具体的逻辑处理啊,回来看着我有调用具体方法吗,我只是把环绕通知start什么ADD方法执行了对吧,这before一个before。

一个around,我有执行具体的代码逻辑吗,那个艾特操作有执行吗,没有吧,记住啊,还没执行啊,没执行,别慌别慌,我来往下走,往下走,点invoke,点m proceed,它这个里面为什么没有处理逻辑啊。

提问题,after里面为什么没有处理逻辑,为啥,你知道我在说啥吗,同学们。

系列 5:P44:44、AOP的实现原理 - 马士兵学堂 - BV1E34y1w773

它会调用下一个进行执行的,所以它是会被后续执行的,因此点mi proceed之后又回到super里面了,我再取谁,第四个谁叫after return吧,是不是该我们的return了。

当我在执行我们的return之后,我再往下走点Emo,这第一个叫mi点proceed,我是不是又执行mi点proceed,再回去再叫super再取谁,after return那个throwing吧。

我再往下走,点invoke下之后又回哪又回哪儿,终于该回到我们当前的,是复制那个调那个那个那个那个链里边去了,点进去点完之后点super,这个时候我想问一下,我们所有的消息通知我递归完了吗,完了吧。

完了之后好吧,我再往下走一步,看到这个步骤了吗,叫invoke,Join point,点FC进去,进来之后点invoke,再点INIT,往下走,点invoke,点完之后,你看他跳到哪了,同学们。

是不是自己的逻辑,是不是自己逻辑,所以你会发现一件神奇的事情,什么事情,当我们在执行具体的一个消息通知的时候,我在这里面进行递归的时候,我只有当执行到这块的时候,我才能执行具体的方法,逻辑是不是意思。

而每次我都需要把我的链执行完,才会执行到当前这个方法。

所以我想问一下前面的排序,前面的这个执行这个advice,最本质的目的是为了啥,来看一句话,只有当所有的通知执行完毕之后,才会调用具体的方法,叫实际的方法,而之前啊调用的advice只是为了执行什么。

注意哪,通知的就只是为了指定,什么叫通知的执行顺序好吧,把链,中的执行逻辑都罗列清楚好吧,按照具体的方法进行返回操作,而这个时候其实我们可以做到一个结论,什么结论我们所有的看好了啊。

After returning,好吧,包括后续的after throwing,他们都是在什么时候执行的,同学们,叫都是,在实际的逻辑代码之后执行的好吧,而我们所说的什么东西叫before,好吧。

还有我们的around,在前部分,它们两块是在哪执行的,在具体的代码执行之前执行的吧,所以我不管我怎么去便利当桥链,我只是为了把什么,在前置和后置的这些方法给罗列清楚。

当我执行完毕之后,可以干嘛了,返回返回,当我这返回返回之后,我问一下,我现在第一个应该执行哪个通知,该听哪个了,执行哪个,谁告诉我是after吗,是around吗。

这个链的目的是为了啥,同学们,Expose,哎呀刚刚是以这样一个顺序来执行的,当我执行完了之后,你发现了执行逻辑是在最后面执行的,如果你在最后一个执行的话,我在原路返回的时候,我会怎么反,我会怎么反。

如果你报异常了,After three,如果你没报异常是谁,after return吧。

是这意思啊,来返回去啊,看好了,反好吧,再往下翻,再往回返,回到这块再发,你看一下当前是哪个类,哪个类apple throwing,它里面有异常吗,没有异常,没有异常,我是不是直接回去了。

回去之后再回来,你告诉我这是哪个类,after returning吧,是不是return,我该执行after return的一个里面的逻辑了吧,点不进去,加之进去执行好吧,再执行,往下走往下走。

invoke就往下走,往下走走走走,Invoke,然后呢点击voke invoke,这打谁谁的老师听见吗,当我执行完这步之后,你看一下具体代码逻辑,around先执行对吧,at的方法执行完了。

执行完成之后,我方法开始执行完成了,这是什么,执行结束了吧,After returning,然后呢,再返回走走走走走走,再回来回来返回返回再返回,这是哪个方法,是哪个,该after了吧。

是不是我执行完之后,下一个是谁,我还有必要执行我们对应的before吗,before还有吗,没了吧,是返回返回去之后最后是谁,最后谁是不是around,后半部分我是把around后半部分执行完整。

完成之后,我是不是就结束了,当前这个量是不是执行结束了,真结束后再返回返回返回返回返回,是不是到结果了,结果等于几等于二吧,我是把结果打印就可以了。

看明白这意思吗,它只是为了维护当前这个链的一个,具体的调用逻辑和调用关系,你把这东西说清楚了,如果你把这手机放到这对吗,对不对,同学们,你们刚刚说在b for后面对吗,不对呀,那没在这儿做呀。

是不是在做,在所有的advice都执行完成之后,在最后一步的时候,才会调用我们具体的一个逻辑,而前面都只是为了什么,我不写了,你刚刚一样,其他东西都只是为了捋回我们对应的一个,执行顺序而已。

执行顺序而已,就这样搞清楚了,好吧哎呀,我真累啊,这个这个这个这个讲的就比较麻烦了,太麻烦,这东西啊,没办法,你只能去慢慢去抠,慢慢去理解这些东西,慢慢理解这些东西啊,那before方法是先执行的吧。

刚刚讲别人讲了个啥。

谁先执行的,谁先执行的,谁先执行的,around吧,对方就是比谁before吧,完了之后呢,after吧,不retinue嘛,然后是after吧,然后是我们的环绕通知吧,是不是正好相对的环绕环绕好吧。

Before after after the return,是不是这意思啊,所以你要理清楚当前这样一个顺序,好,得理清当前这样一个顺序,OK这东西啊。

你理解清楚之后好吧,还有东西来看下面这个问题,看下面的东西,这个问题是我这节课最想讲的,结果到现在还没讲到,往上看这玩意儿,同学们想明白一件事,想明白一件事,源码好吧,如果设计简单了,设计。

简单当然了好吧,那么在某一个方面会有缺失,哪个缺失会在哪个方面有缺失,同学们对扩展性,扩展性好会在扩展性方面有缺失的,好了,这东西啊,所有的代码,spring里面所有代码它写的多复杂多乱。

包括说它抽象出来一丢丢的接口好吧,一堆的时间内,这东西最主要目的就是为了做扩展,永远记住他是一个spring全家桶里面的一个基石,最底层的一个支撑,如果它的扩展性不好的话,它的扩展性不好的话。

我们现在用的spring boot spring cloud都将不复存在,你不可能说我每次新出来一个框架,就做一个历史性的变革,这不可能,这不可能,如果你每次出来新东西之后。

你都要把之前的所有代码重新干掉,重来一遍,那就完犊子吗,没完了,就这样,你要想明白了好吧,只不过之前我们在进行这个拦截器件,理解的时候,大部分人是怎么理解的,怎么理解的,第一个链好吧。

我这里面直接指向下一个链,我们下一个链开始执行下一个了之后,我再执行下一个链,我再执行下一个链,他没有这个chain这个外部空间的一个组织,所以跟之前的理解可能不太一样,OK好这一定要注意了好吧。

那最后聊一个问题,这玩意如果要自己通过a OP的方式,来实现一个统一的事物功能,我们应该怎么做,或者说你会怎么做,别别别什么爱的tral spring是这么干的,你自己实现,你说我要准备什么东西。

你自己如果实现的话,我需要执行什么东西,什么叫事务处理啊,我问一下事务的处理,跟我们刚刚日志的处理一样不一样,一样不一样,不一样哪儿不一样好了,举个例子,这是数据库操作,可以吧好吧,这是我们具体的操作。

给数据库操作,操作数据库在操作数据库之前好吧,我一定要干嘛,你们说的打开连接对吧,准备好事,事务对象好吧,然后在后续的时候我又提交,这叫开启,叫打开连接,好吧,开启事务对象,开启事务是不是这块。

然后他执行完成之后,这分两种情况,非常情况怎样情况,歪的这个东西不管了好吧,说是否有异常,如果有异常,有异常怎么做回滚,对不对,回滚如果没异常怎么办,没异常怎么办,提交,这是不是整体的逻辑,是吧。

最简单的一个逻辑,这个东西如果让我们自己来实现的话,我会怎么办,你是不是要选择对应的一个通知了,你告诉我我选择什么通知,我选的什么通知比较合适,你告诉我,好了,毫无疑问一点回归应该用什么。

会用什么throwing吗,After three,是不是东西提交呢,提交用什么,return对吧,开启用什么,before吧,是不是这几个这能理解吧,这是一对应上的好吧,我现在如果想通过,来迭代一下。

叫通过,一个消息通知好吧,来搞定所有事怎么办,能做到吗,不可能为什么不可能,里面有around,是不是可以AROUND,有了around之后好吧。

我只需要在around里面把我们的after throwing,内嵌进去不就行了吗,你不就少了个回滚吗,我把ipathrow in嵌进去行不行,行行不行,行吗,同学们,行吧好了,这东西如果能理解的话。

勇敢你是你是过来抬杠的吗,好了,如果这东西可以的话,在spring里面就这么干的,来transition interceptor,有这样一类。

有这样一个类,来我们打开看一眼好吧,我抬杠没事,最不怕的就是就是抬杠,来往这儿看,在我们的transition intercept里面,有一个非常核心的叫什么叫invoke吧,是不是有invoke。

是不是Emo,我们都知道每个通知在进行执行的时候,他一定会叫invoke方法,在invoke里面有一个invoke with within transition,点它进来之后好吧,你看一下它的过程。

看看它的过程,先找一些核心东西,这代码能看懂,这一行能不能能不能看懂,能看懂吧,干嘛的,叫emote proceed with invocation,是不进行后续实际逻辑的一个处理。

这是我们实际逻辑的一个处理,在这个之前都是准备事务对象打开连接,是不是做做这样一件事,好吧,你注意看,如果在执行具体逻辑的一个处理过程中,处理过程中我突然出现异常了,我怎么办,看它的名称描述叫什么。

听同学们叫complete transition after sowing嘛,如果我这个异常没发生,我要正常提交怎么办,怎么办。

叫什么叫commit transition after returning。

是不是我前面写的方式,是还不是,是吧,是啥东西,有了这仨东西了,我能不能把这仨东西揉到一块,你刚刚我带你们看过源码了,你们应该能体会到所谓的before也好也好,五种消息通知,消息通知,只是。

spring中好吧,原生提供的支持,通知自己在进行实现的时候好吧,可以参考实现好吧,但是没必要非用,费用它本身的模板看明白了吗,我不是说他定义好物种通知,我就只用这五种通知,我自己扩展不就完了吗。

能理解意思吗,好吧,而在进行扩展的时候,就意味着一件事可以干什么事,可以将各种通知到,好吧,模模式或者说更通知的编写方式,拿过来进行,借鉴吗,借鉴借鉴借鉴,看白意思了吗,啊这就是这个框架。

它比较牛的地方是为什么为什么这么牛,你就想一下,刚刚我们看这个max interceptor的时候,呃,不是interceptor的时候,他有实现任何after before这些东西吗,有时间吗。

没有吧,就实现了一个什么东西叫method interceptor,After before around,什么东西,玩蛋去好吧,我自己来实现我们自己的逻辑,而不需要严格遵循什么before阿。

这东西只是在框架里面。

他提供这种原生的支持,那我问一个问题,同学们如果现在就想让你通过after before,不是啊。

系列 5:P45:45、面试问到了AOP如何去回答? - 马士兵学堂 - BV1E34y1w773

是我能不能,能不能别动都不动啊,我就用他原声提供的通知,能不能能吧,都拆分开了吗,肯定可以吗,但是我把它整合到一块,是不是也可以,所以同学们记住了,看源码最主要的目的是为了啥,我已经讲了很多的源码课了。

很多VIP同学还是非P,大家都理解不了,老师,我为什么要看源码,剩下这件事情,为什么太阳马,原因是啥,最简单的一点最简单的一点是什么,面试面试官会问,所以我要用它好吧,第二点是干嘛,借鉴设计思想。

借鉴他的设计思想,好这事是很重要的,当你借鉴完三思想之后,第三步可以干什么事,这个这个同学应该是我们的我们的VIP啊,这样干嘛,二次开发,二次开发,什么叫二次开发,很多同学入职到一些大的外包公司。

或入到一些大的平台之后,好吧,你会发现一件事,什么事,别人已经把接口都封装好了,当别人把这些接口我都封装好了之后,你调的只有API,你掉了只有API,当你调了API之后好吧,你又不知道底层怎么实现的。

别人怎么做这个通用性的,如果我要扩展的话,我怎么办,我能不能扩展,如果让你在这个基础上做扩展,你会吗,你能吗,最主要的一件事,我在上课之前之前给VIP说,上课的时候说过一句话,什么话叫为所欲为。

所以这里面的核心代码你是一定要看的啊,面试是我们最基本的一个追求,但更多的是什么,你要从中学到东西,这最核心的不说别的,就光设计模式要不要学,咱们写代码里面最多用的是谁,单例模式对吧。

工厂模式用一下代理用的很少,原版里有多用用多种设计模式,孩子去了,孩子去了,这东西你必须要知道,因为在考量具体的一个程序的健,壮性和扩展性的时候,你的设计模式必须要良好,应用没招,所以这东西一定要去看。

一定要学,很重要,明白了吗,大家也发现了,我今天给你们讲起来比较费劲,为什么比较费劲,你们听的可能也很难受啊,我知道我有我有大概的感受,你们可能听起来也不太舒服,感觉哪哪都不理解,特别是第一次来听同学。

你知道问题出在什么地方吗,啊不是因为你跟你跟你跟你没关系好吧,跟你没关系啊,勇敢不是因为你啊,你提问题是好事,你现在推着,你现在推着这个课程再往前走,你其实问题都是好事儿,但问题的原因是什么。

是因为一个很重要的点,叫前置知识缺失,这东西不知道你理解不理解,我刚刚一直说一句话,一直说一句话,我说为什么我之前公开课的时候,从来没有讲AOP,因为不敢讲,如果你把IOC相关的东西没理解清楚好吧。

a OP你是理解不了的,明白意思吗,它是这样的一个具体的关系好吧,LC是啥,AB是啥,我们其实可以思考一件事,同学们什么事,刚开始spring出来之前,spring出来之前好吧。

spring出来之前你注意了,它就是一个容器,容器里面代表什么,有一堆的对象,但是对象什么时候创建,创建是不是第一个问题好吧,怎么,创建对吧,动态代理,代理如何生成生成,具体的对象,对吧。

像这像这东西如何,解析注解如何加载,配置文件,并且解析,这都是前置的,这些过程包括初始化干了什么事,干了什么,之前他一直问我一个问题,说老师你能给我解释一下别人卡文件,不需要你给我解释一下。

这两个注解叫at呃,Post concert,好吧,count和at pray destroy。

这是什么情况,这节看这么难受啊,At post disconstruction,可能这东西对吧,包括at pray destroy。

老师这样做,什么时候用的,你们知道吗,这样数学什么时候用的,有没有人知道,有人知道吗,哎没人说话了,怎么,什么,之后执行初始化销毁哪个类,什么时机什么时机,触发了,容器启动之后。

能敢说的再再模糊一点吗,哪,All to wear,诶怎么没有了,auto wd这东西吧好吧,在当前这一类的时候,有什么at where怎么处理的,at value怎么处理的,在这一类的上面。

它有一个父类叫什么,走呃不是,这找一个叫common annotation,Being postprocessor,这里面有什么resource,怎么进行处理的好吧,而在这个类上面。

它继承了一个什么叫INIT,Init,里面有什么找找时间内往哪看哪去了,构造方法呢,看这有什么post constructor,Pray destroy,我什么时候住进去的。

我应该怎么对它进行相关的一个解析工作,是不是都有,你在这个common里面,你能看到一个构造方法,找一下看看post contra predestroy,看到了吗,我是不是在二进调用的,看完意思了吗。

再比如说注解什么时候解析的,我就问一个问题,同学们,我就问一下这个at configuration什么时候解析的,这周几你们现在用的很多,它是解析处理的,如果你用纯注解的话。

at import什么时候处理的,知道吗,什么时候处理,说类名,说这类名就行,不要不要就什么时机类名你知道吗,哪个类有没有知道,好了,李海滨说知道行突破不对啊,李海滨说对了。

叫什么叫configure ration,Class,Post processor,在这个类里面进行相关的一个处理的好吧。

哪个对哪个方法来找一下,叫post process registry,给他,找他找他,往上看什么东西是否被component修饰了好吧,这个东西process any at property。

Source annotation,Process any component,Scan annotation,Properties,Process any import annotation,好吧。

process involu in individual是吧,不会多啊好吧,at in什么时候处理的好吧,看到东西了吗,你要知道他是在哪做的,这个时候你只有把这些细节点你都搞清楚了啊,才会有一件事。

同学们什么事,叫面试的时候好吧,不会垮掉,这才是很重要的,这才是很重要的,现在面试跟原来面试还是一样吗,没人应该应该有感受吧,前面是怎么样的啊,原来面试原来面试来。

你给我说一下spring bean的生命周期,你把网上一个文章或者一个图拿下来背诵一下,背完之后了事了好,我觉得你会结束了,现在会问什么来,你告诉我,invoke不是invoke aware接口干嘛的。

对吧,你告诉我,Init method,干嘛的,你再告诉我动态代理,对象什么时候生成的,对吧,再告诉我如何生成的,是这意思,像这些细节,面试官会一直不停的追着你问下去问下去,问到你答不上来为止。

蛋包饭说了一句话,什么说现在都是聊一聊spring a OP,然后一边说一边追问,连问到底,就这意思,为什么呀,为什么为什么会有这样一个情况,同学们是知道原因在哪,人在哪,原因其实非常简单。

人太多了好吧,需要选择优秀的人才,原来比如说举个例子,我之前其实举举过这个例子,什么例子同样原来都是100分的考卷,100分考卷对于原来而言,你答个60分好了,我就要你了好吧,但对于现在而言。

你达不到90分,我就不要你,很简单一个对比,所以要求大家干嘛,对技术的细节,好吧,必须要掌握清楚,这没招啊,逼着我们去这么做,也不要抱怨什么内卷啊,什么乱七八糟的东西,不要抱怨这件事情。

技术就这么发展的,慢慢这个行业留下来的人是什么人,高精尖人才,你能活下来的一定是这样,你猜如果你就会点COD,就会点基本功能完蛋,这个行业里面你一定混不久,你可以入行,可以干干几年,但是一定混不长。

你会长,我们就拿spring源码来说,你觉得spring源码你要看多久就能学会,你自己看看多久,多久3年十年,还有吗,5年八个月你要拖多长时间,我刚说过,在我们的VIP课程里面,光这光spring源码。

这里面全部都讲的spring。

我给你看个东西,看看东西,这是我在我们的VIP页面里面讲东西,第一节开班典礼,第二节,第三节,第四节,第五节,每节课讲不同东西,现在已经讲到第28节了,明天啊不是明天下周一是第29节。

每节课至少是两个小时以上,随便打开一节,随便开一节好吧,是不是看。

多长时间,两小时31分钟看清了吗,很多东西是一定通过时间的堆积时间,你说短短几个小时之内,我把一个很多东西给你讲清楚,可能吗,不可能一定是需要时间的,有了时间之后好吧,还要注意一件什么事儿叫效率。

为什么很多同学一直在聊,一直让我讲a OP,你从网上从这个地方你找不到对应的资料,没招了,你说老师你讲一下吧,好了,我先讲一下,讲完之后我之后可能都不会讲了,这东西真的太难理解了啊。

VIP里面我已经讲的东西了,但之后我不会讲了,那你想想你还要学要学什么东西,spring源码,spring mvc对吧,后面你要看什么spring boot,后面呢你看看spring cloud,对吧。

在中间过程里面你可能需要穿插my body is对吧,在spring boot里面你需要穿插tomcat,这都是你要学习的基本的必备的点,必须要学,那么这东西什么东西呢,架构师,武器中全部。

都讲好意思吗,会不会学着学着猝死,我还没听说过有谁学着学着猝死的,所以下面到一个非常核心且重要的环节,什么环节叫广告环节,我要告诉你们,你们必须要看这东西。

string说spring boot和tom cat有什么关系,有啥关系啊,原来你在用SSM的时候,你需要外置一个tomcat,在book里面是有内嵌的,怎么内嵌进去的,为什么内线我就问一个问题。

spring里面如果我想内嵌tomcat的话,以你现在了解你觉得应该在哪陷进去,或者说应该从哪嵌进去,你觉得你自己感觉从哪儿,依赖是依赖吗。

哎我就说你们不会来随便打开一个项目,这是我之前写的一个spring boot项目,好吧,之前写的一个案例的一个东西,我们打开我们启动类,这是启动代码,右击debug,来点F7进来F7进去进去。

点run往下走,走走走走走,走到这行点它点它点它往下走,内行走走走,往这看叫on reflesh,点它这个东西叫什么,同学们看这叫啥,你告诉我,这叫什么,create web server吧。

点进去好吧,往下走往下走往下走,这东西叫get web server server factory,它返回什么对象,什么对象叫tomcat server,Web server factory。

那么在最终在后面是不是可以干嘛,叫on start up吧。

我是不是可以启动我们当前的tomcat服务了,看完意思了吗,你说你对这东西不熟,这东西不熟,为什么内嵌怎么内嵌的,问你这样的问题,你怎么答,你怎么答,真的不是为了给大家讲源码,为了给大家拖时间。

所以我把这个课讲了这么久,我还想早点结束呢,到今早我早没事,没办法了好吧,必须现在面试的就这么要求,你必须要把技术的细节都搞得倍儿清楚,必须要把技术的细节,搞清楚搞不清楚,你就没办法跟别人竞争和pk。

老师在家讲课吗,我不在家讲课,在公司现在还没下班,在公司里面呢,在公司里面好吧,所以就问一个问题,如果把这些源码的东西都给你掰开了,揉碎了,给你讲的非常非常清楚,非常非常清楚好吧,那么能学会源码吗。

如果一行一行带着你讲,能看懂吗,你就想一下,我刚刚给你们展示我对应的一个源码的时候,源码的时候我给你看看这注释了吗,虽然不是每行代码都有注释,但是加注释了吧,加点注释之后能不能方便你进行理解,能吧哈。

开车为什么非要懂发动机构造呀,公司怎么想的呀,大哥你想一件事,你现在在公司里面,如果你在做一些cod的项目,你公司能活下去吗,你公司里面必须要有自己的技术堡垒啊,或者技术壁垒啊,你没有技术壁垒的话。

你在公司里面怎么活下去,你公司里面凭什么拿项目,你要留点别人不会的东西,你公司才能活下去,所以公司对于技术的要求好吧,对技术追求会越来越多,越来越高,这没招,这就是这个行业里面出现了一个趋势好吧。

所以这个问题能看懂吗,就这30节课,二八节课你看完之后你觉得怎么样,每节课至少两个小时,目前已经讲了56个小时了,后面还要讲多久,我不确定,至少十节课左右,这种东西你告诉你现在还学不会。

你四五个小时你听一下,你觉得能学会吗,你需要成体系的学习,这是很多同学在面试的时候,经常被问到的一个点或者被反馈出来的信息,看你们有没有什么信息,很简单,一件事说知识不成体系好吧,知识碎片化。

有人收到过,有人收到过当前这样的一些评语吗。

知道过吗。

系列 5:P46:46、Spring IOC容器的核心实现原理 - 马士兵学堂 - BV1E34y1w773

谁来告诉我spring到底是什么,谁来告诉我spring到底是什么,当然有很多同学会给出一些描述啊,比如说老师,首先第一点他是个框架啊,还有人说春天的好吧,第二点它是个什么容器吧。

我们一般都说spring容器对不对,第三个我希望大家能明确一点,什么叫生态,这是我给的一个知识,什么意思,因为你们现在在基本的呃工作中,要不然用spring,要不然用spring boot。

要不然用spring cloud,基本上都是spring这个全家桶里面的一体系东西,而这些东西里面spring就是最基本和最根本的基石,你把这块了解清楚了才可以,而他现在主流面试的时候。

他上来之后不会问你一些定向的问题,而问你一些什么,谈一下你对spring的理解,或者谈一下你对病的理解,谈一下你对bean生命周期的理解,基本上是以这样的一个方式来问问题了。

那遇到这样的一些理解性的问题,或者说非常宽泛的问题的时候,我们到底应该如何去进行回答呢,谁能告诉我,如果一问到spring,你现在还是只说说一个IOC,说一个a OP,我告诉大家,你就别说了。

这俩东西单打的话肯定是不够的,肯定是不够的,你需要把里面的一些细节点都答清楚,把里面的每一个环节能知道能出多少,输多少,把这些东西一定要完整进行一个转化,那咱们来聊呢,还是一样。

spring我们用起来非常简单,为什么简单,谁能告诉我最核心的点在于,spring帮我们把我们呃应用程序里面所需要的这些,bean对象是帮我们管理起来了,而在进行管理的时候,首先它是个什么,是个容器吧。

所以我这先画一个大格子,它是一个容器,容器的话是什么意思啊,里面一定是放东西的,比如说在程序里面放的是一个一个的bean对象,对吧,一堆并对象你想放多少个,放多少个,当你了解到这个环节的时候。

还不够还不够,还需要具备很多的知识,具备啥,你想吧,spring帮我们来管理人管管理并对象,那spring是怎么知道这些并对象是哪些呢,或者说我应该创建哪些基本的并对象呢,他是怎么理解这件事情的啊。

比如说反射,反射是创建对象的一种方式,这时候根据类型,根据注解,其实这个时候我希望同学们在看源码的时候,先以应用入手,你把应用的点理解透了之后再说什么,这是什么原理,然后下一步再说源码。

我们在用的时候怎么用啊,很简单了,我如果想声明一个对象的话,我一般会在类上面加一些注解,比如说at controller对吧,at service对吧,ADD component是不是这样的一些东西。

除了这些东西之外,这是我们用注解的方式吧,除了用注解之外,当然我还可以选择另外一种叫配置文件,那么对吧,当然现在主流的开发环境里面,XML可能几乎已经不用了,或者用的已经很少了啊,但是我想问一下。

插画也好,还是我们这些注解也好,它到底说的是什么东西,或者说我们为什么要用JA,或者为什么要用注解,它到底代表什么意思,谁能给我解释一下,java config不就是一些configuration吗。

配置类吗,好了空白格说了一个非常重要的描述,叫bean的描述信息,也就是说,不管我用XML文件的方式,还是我用注解的方式,在这两个里面定义的全部都是什,么叫bean的定义信息,写一下,BD定义信息。

所以我希望你能够先把这个东西掌握了,为什么,因为在整个spring源码里面,还有一个非常重要且核心的一个接口,叫做什么呢,叫做bean definition,是不是这玩意儿必须要有这样的东西。

它是一个接口好吧,当然接口里面会有一些具体的实现子类子类,我们先不管,我们先把借口给写出来,那你就要思考过你,你就要想一件事,想什么事情,我用XM2也好,用注解也好。

当我定义好这些bean的定义信息之后,我需要干嘛,是不是需要把它交给我们的容器,容器在识别到这些bean definition之后,我才能够根据bean definition里面的一些相关信息。

来把我需要的对象给创建出来,是不是这样一个逻辑啊,所以在这块它有一个最基本的环节,从这儿我写过来,我们的XML文件也好,还是我们的bean definition也好看,最终需要的是什么啊。

还是我们注解也好,最终都会转成一个bean definition,而我有了bean definition之后可以干什么事,直接来点,可以进行实例化操作,比如说或者换句话叫创建对象,这没问题吧。

从XML到BEDIVISION到创建对象,有人说老师这个XML我怎么解析啊,或者说我的注解我怎么解析啊,有人会吗,拆包怎么解析,谁能告诉我,如果让你来做这件事情的话,你会怎么做,思考这件事情怎么做。

啊咋做,读文件吧,首先我通过IO流的方式对吧,把我们这个文件给读取回来,当我读取回来之后,说白了它就是一堆的字符串,字符串存在,它本身是没意义的,我需要把这个字符串进行一些解析,而解析的时候。

XML本身自己是自带格式的吧,是不是很合适,所以我可以用一些现成的工具,比如说叫DOMOJ对吧,比如说SAX这样的方式,来把我们这些读取到的字符串来转成一系列的,什么叫document对象。

当我有了document对象之后,下一步它就变成了一堆具备父子节点关系的,node节点吧,然后我根据我能够节点循环遍历,是不能取出里面具体的数据值,当我取到这些具体的数据值之后。

是不是可以把我们这些数据值再给到我们的,并在分析选对象中,是不是这意思,那一样的注解是不是也一样的,注解怎么做,注解我先获取到某个类上面的一些注解信息,当我有这些信息之后,我获取对应的class。

有了具体的class之后,我是不是就可以进行相关对象的一个创建了,而我这些class信息也好,name属性也好,value属性也好,我是不是可以直接放到我们的bean,definition里面去。

也就是说不管你是XM还是我注解,我只是解析的方式不同而已,但最终殊途同归,都会合并到bean definition中来,这句话能理解,同学给老师扣一能听懂吗。

这没问题吧,如果你不信的话,我们可以看一些具体的代码,比如说我先找到基本的一个东西叫bean definition。

之前一直有人理解不了老师,这个BEDATION到底是个啥,好吧,你看到了它是一个interface,interface的话里面一定有对应的子类实现,往下找找它对应的属性值。

比如说有一种属性叫parent name,可以设置父类的名称,好吧,叫bin class,是我们的class呃,那个完全限定名,比如说scope是单例的还是圆形的对吧,比如说lin it是不是人家来的。

比如depends on,是不是我需要依赖其他的病对象,我是不是可以把这些属性值全部都设置进去了,当然这些东西是在子类里面进行相关实现了。

但是我已经能看到当前接口里面,表示的具体意义了好吧,因为你们都写过这些东西啊,有点跟不上了,这也跟不上了,来我写一个,这有啥跟不上的,来写一下最基本的YOUTUMB那个注解,你们应该都会啊。

XML可能很多人没写了,我写一个XML好吧,id等于比如说data source,这玩意应该用的最多的,然后class等于写上com点阿里巴巴点,有一点错,Data source,不就写这样的东西吗。

对吧,当你写完这些东西之后,看不到,能看到吗,刷新一下好吧,刷新一下,唉这真是命运多舛,想上个课就这么难吗,来喜欢一个病对象,然后里面我可以配置一些基本的属性信息,比如property。

然后name等于U2,value等于dollar,大括号,JDBC点U2R,然后下面再来一个,gravity name等于username,value等于到了大括号JDEC点。

username有这样的东西吗,这不就是我们定义好的一个配置文件吗,对吧,当我订好这东西之后,我可以经过一系列的解析,把这些具体的属性值全部都放到bean,在飞机里面去,当我放到B,但是你审里面去之后。

就意味着,我已经知道我要创建哪些最基本的对象了,而我有了这些最基本对象之后,是不是可以进行对象创建了,那我问一下对象创建到底应该怎么创建,是用new的方式还是用反射的方式,new还是反射,反射吧。

几乎所有的框架用的都是反射,当然很多同学可能会看到一些帖子的描述,什么呢,说老师反射效率不是很低吗,有这样控制吗,反射效率低啊,为什么还有反射呢啊,注意了,反射它是足够灵活的啊,足够灵活的啊。

但是效率低,你注意了,我之前说过一个数量级,我也是从一个帖子上看的,这个没有,我自己没实际测过,当你创建10万个以上对象的时候,反射才可能会出现性能问题,当你创建少量对象的时候。

是不会出现任何性能问题吧,明白这意思了吗,不会有什么新的问题,所以大家不需要去考虑这件事情,反正足够灵活,当我获取到一个类的完全限定名的时候,就报名加类名好,会到报名家里面的时候。

我就可以根据这个字符串来创建出来,我们具体的一个对象就这么简单啊,所以这是它整体的一个流程,当然如果我直接以这样的方式去创建,我们具体的一个对象的话,那spring就显得太简单了好吧。

而且如果是这样的话,spring它不会有一个非常完整,或者说并不会有这么完整的一个生态的,那我就想问一件事,如果这个过程不是这么简单,就意味着这条路线是不存在的,中间一定包含了其他对应的一些环节。

什么环节,我举个例子,同学们,你觉得spring能活到现在,或者他现在有一整个完整的生态,完整的生态。

系列 5:P47:47、BeanFactoryPostProcessor接口详解 - 马士兵学堂 - BV1E34y1w773

也是因为啥,啊是因为什么,谁能告诉我好了,同学们基本上都说到了,老师基本一个点叫扩展性,其实这点是你们在看源码的时候,最应该学习的知识,很多同学在写代码的时候,其实只是为了完成我们具体的一个业务。

逻辑功能,你压根不会考虑什么扩展性之类的点,可能就不会考虑这些东西会考的东西,但是你看原版的时候,发现原版里面很多地方都是可观的,留了一堆的口子,让我们能够随意对他进行扩展和优化,就这么简单好吧。

而且你可以按照自己的需求来进行,相关的定义和具体的处理工作怎么做,一会儿我再来进行相关的一个描述,我们先放一放,你知道扩展性这点就够了,当扩展计算清楚之后,这个时候你就要去思考一件事了,现在我有了XM。

有了注解,有了bean definition,我可以进行对象创建了,有人说老师不对,你这里面少了一个非常重要的东西,什么叫bean factory,基本上你们在学习spring的时候,别人都告诉你。

老师我们刚开始用的对象叫been factory,这玩意怎么理解啊,这玩意怎么理解,有人把它翻译成叫并工厂,还有其他理解方式吗,对象工程还有吗,其实我觉得如果你把它直接翻译成兵工厂。

这样的方式或这样的一些说法,其实不太准确,为什么,为什么呢,你可以详细来看一下这个bean definition,在源码里面,bean factory它到底是个啥玩意儿,你看到它是个什么。

它是一个接口吧,首先那个接interface好吧,是个接口,这个接口用来干什么使的呢,里面有一堆的描述信息,我们可以来看第一句话叫the root interface。

For assessing a spring beer,什么意思,什么意思,说它是一个根接口对吧,干嘛呢,用来访问一个spring的电容器,刚刚我已经说过了,我们的spring本身它就是一个容器吧。

容器里面可以放具体的一些bean对象,而我们的b factory它更多是一个入口,为什么把它称之为入口呢,你想一件事,你在用spring框架的时候,如果你想自己去获取某一个bean对象,你会怎么来获取。

你会怎么做,告诉我你怎么写代码,怎么写代码,比如说老师我是这么写的,叫什么context,点get be对吧,里面可以写上我们具体的一些类别的person class。

这个时候我就能获取到我们这个person对象了,是不是这么大的,那老师contest跟我们的b factory好像没啥关系吧,如果你去面试面过的话,就应该知道面试官有时候可能会问你一个问题。

说来你告诉我application context和bean factory,他们两个到底是什么样的关系,这又涉及到两个接口,第一个叫bean factory,对吧。

还有一个叫application contest,这里面有关系吗,他们俩什么关系啊,父子注意了,Application context,它继承了我们的bean factory。

提供了一系列更加完善的功能,听明白了吗,它提供了一系列更加完善的功能啊,而并不是说他们两个完全没有。

如果你可以打开源码的话,你可以看一下这东西叫application la casion context。

找到这个接口,然后呢选中右击so diagram,你可以看到他一系列的继承关系好吧,往下看它这个接口吧,它是不是嗯不对,它是不是继承了并返回这个接口,看没意思了吗,好吧,那英语老师他这样实现什么意义啊。

它提供了bean factory里啊。

它比较单一,里面只提供了一堆的一系列什么呢,叫get并的方法,但get定的方法可能不太够使不太够用,所以application contest对它做了某些最基本的扩展功能,提供了更加完善的一些方法。

明白这意思吧,好所以把这件事我希望他们能理解清楚了,也就是说你虽然用的是我们的applicant contest,但说白了继承的还是bean factory的方法,所以这时候就问题来了。

老师这个bean factory到底怎么理解,到底怎么理解,你可以把它理解为是一个入口,也可以直接把它就等同于我们对应的容器对象,能明白这句话吗,因为我们这些对象。

不管你的bean definition也好,还是你实例化好之后存在对象也好,他都放在某一个容器里面,而容器是需要bean factor来进行访问的。

这时候你可以把bean factter的某一个实现子类,就当做我们整体的容器,比如说面试中问的比较多的是啥,有一个容器面试中几乎可能会提到啊,如果你回答比较多的话,就会提到有人知道这玩意儿吗。

叫default,Easible,Being factory,有听过这玩意吗,听过的扣一没听过,扣二没见过,注意了,它就是我们所创建的整个spring容器,也就是说我们所有的B类项。

其实都在default visible并factory里面进行存放的,一会儿,我可以带你们看一下整体流程和整体页码,好我们先扔一边,所以这东西我希望你能够先认识到了,当把这东西扔到之后。

你就说它是我们的容器,它是being factory一个子类,我可以把bean factory就等同于我们对应的容器,当我需要访问的时候,可以直接通过bean factory来访问容器里面的。

一些对象值或者一些属性值了,那我问一下,我能不能通过bean factory来获取bean definition,能还是不能,看这个问题啊。

我能不能通过bean factory来获取我们的bean definition,能还是不能,能不能有人说能有人说不能,能不能取决于什么东西,你看一下它里面有没有具体的方法。

不就完了吗,这东西我们没必要吵的,点开之后来看一下,有个东西叫get bean definition吗,有没有有对应这样的方法吗,好像没有,对不对,没有你也没必要慌,为什么它是一个顶层接口。

既然是一个顶级接口的话,就意味着它一定包含了一堆,或者一系列的实现子类,所以如果复制上面没有的话,我们可以去子类里面进行查找,好吧,来找个东西,这玩意有东西叫CONFIGABLE。

并并并factory点它之后,我们可以来找一个东西叫get,哪去了,看到啊,有get bean class order,有get bean expression,Recover。

get depends是什么东西,这里面是不是比我们刚刚那里面,包含更多的一些属性方法,让他看啊,我刚刚是打开一个子类,当我打开子类之后,它里面是不是提供了更多的一些方法,除此之外你还能看什么。

还有团长,你通过它知道它在子类里面,一定包含了一堆的扩展实现,虽然我的父类接口里面没有,但是我子类接口里面有,比如说我带你们看一个对象,那你看一下啊,Prepost process。

看来我现在点开是当前这个词类,他的继承关系啊,它实现了libbean factory,然后离实现了configable bean factory。

confiable bean factory上面有哪儿去了,叫继承的bean factory,再往上翻有bean factory,因为它有一系列的继承关系。

我们不管这个继承关系了,打开它在里面找一个方法叫get,看着你看到啥,他们告诉我看到什么叫get bean definition,能不能看到,能看到吗,就说spring源码它为什么这么难。

或者你们看起来感觉这么乱,最关键和最核心的点在于,它存在了一堆的接口或者一堆的抽象类,这抽象类的继承关系会变得非常复杂,你在找具体的实现的时候,你可能不太容易找,所以你需要一层一层去捋这玩意儿。

像我刚刚说的bean factory没有get bedefinition,但是我往沿着子类往下找,找到了吗,是不是有东西叫get by definitions。

也就是说我可以通过我们的bean factory对象来获取到,我们具体的bean definition对象,找到之后,我就可以直接获取到了,明白意思了吗,所以这是源码它比较难的地方,你需要一层一层去旅。

如果你不去捋这玩意儿,你压根理解不了里面的核心点,好,这东西我们先扔一边,读完之后来回过头来,现在说了,我有了bean factory之后,我可以根据我们的bean factory。

来获取我们的bean definition,刚刚呢我也写好了一个配置文件,比如这个地方,当我写好这个配置文件之后,问题就又来了,同学们什么问题,大家看一下里面的东西啊。

我这定义了一个data source,有人这么定义过data source吗,这么写过同学给老师扣个一,你们这么写过没有,你们现在不这么干了对吧,都用注解,都用注解,对不对,那我问一下好吧。

我们这样配置文件的方式,这里面哦,我没写引号,没写引号,在这里面存在一些占位符吧,比如说叫dollar j DB c u22,dollar j DB c6到name,这些占位符一般我们会写一个配置文件。

叫dB点properties对吧,然后从这个配置文件里面,把我们需要值给拿过来,替换到我们这个value值里面去,一般情况下我们都是这么干的,是不是这意思,那我问题来了,我在这个步骤这个步骤来进行解析。

装,改成一个bean definition对象的时候,我是否会把这个值也进行一个替换,是还是会还是不会,会吗,不会对结论确实是不会不是应该不会,就是不会,如果不会的话,同学们,你注意了,这个步骤。

它只是把配置文件或者处理这样的方式装载成,并单位时对象了,它不会对里面的值进行处理,那下一个步骤,我就应该通过反射的方式来进行对象创建了,现在指根还没有呢,那我怎么办,这还没有怎么办。

我是不是一定在中间某个环节里面,要把这个值给替换掉,因为我如果不替换的话,我没法进行对象属性赋值了,我肯定会进行替换的,那么在哪替换,有人说了,老师在ban Viper里面进行替换。

有人知道什么叫ban Viper吗,好多同学提到这东西了,Ban raper,他是个啥,什么B方法,它是bean对象的一个包装类,是在我们创建了一个bean对象之后,会把它装载或者包装成一个并发牌对象。

你可以直接把它等同一个bean对象,那个时候对象已经创建好了,你还留着他最近干嘛,不是在这注意了,会在哪进行操作,会在我们整个对象创建之前,记住叫之前把这些属性值全部都替换完成,如果我在对象创建之前。

不把属性值替换完成的话,他后面没办法进行属性赋值了,语文老师在popular bean对象里面进行填充,会的popular对象里面只popular的方法里面,他只会去设置属性值,而不会把值进行替换。

所以在中间一定某一个环节会对它进行扩充,扩充啊,所以这里面会涉及到几个东西,我要给大家说明一下,比如说第一个最简单的,有些东西你们应该见过叫bean post processor,有人见过吗。

或者我把病去掉,叫post processor,前缀不要了,叫post processor,有人见过吗,这个post processor是啥玩意儿,什么东西,前置处理器。

完了第一次有人把它称之为前置处理器啊,有人把它称之为叫后置后置处理器好吧,也有人把它称之为叫增强器,我个人认为增强器说的是比较合适的啊,后置处理器这样翻译过来可能不那么合适,可能不那么合适。

明白意思吗好吧,那增加一什么意思啊,它就是用来完成某些具体的扩展功能实现的,比如说问的最多的两个东西,第一个叫并factory post processor,这是第一个好吧。

还有第二个叫b post processor,这应该是我们在日常工作中,或者说在我们那个面试中,问的最多的两个接口了,他们都是用来进行增强功能实现的,那么他们两个到底有什么样的区别呢,啊有什么区别吗。

区别是啥,很明显了吧,你通过类名就能分辨出来啥区别,针对的操作对象不同嘛,一个针对的是been对象,一个针对的是been factory对象,所以你可以思考一件事,我如果去看这个接口的话。

我如果想对我们的bean factory进行扩展的话,我是不是可以通过我们的bean factory,post processor进行扩展来。

我不不光吹,我给你打开这个接口,你来看一下叫ban favorite post processor,有这样的对象,就这样这样这样一个接口好吧,他说了,他是一个hook,允许用户去自定义。

我们上下文对象的bean definition,看后面那句话啊,翻译好吧,允许for customer modification自定义的修改吧好吧。

Of an application contest bedefinition,某一个应用程序的bean definitions对象吧,我是不是可以通过它来完成某些definition对象,的替换工作。

而你打开这个接口之后,你发现这个接口很好玩,它里面有且仅有一个方法叫post process in factory,其实就把名字翻了个叫bean factory的一个后置处理。

你看到了他传过来的对象是什么,是一个bean factory对象,所以在里面我可以按照这样的方式来获取到bean,definition对象,然后来对bean definition对象进行修改操作。

能这么干吗,可以啊,那怎么来看呀,很简单,找到这个接口,我们依然找一个时间子类。

我这儿不让你们去找了啊,我来直接给你们找到,你往下翻,有一个东西叫police holder configure sport,有这样的一个实现子类,在当前实现子类的上面还是看注释好吧,还是看注释。

他说了没事,我们也找不到,来看看啊,什么东西呢,看注释啊,第一个叫abstract base class,说是一个抽象的基础类,对于什么呢。

叫property resource属性资源configure配置,也就是说它呢是一个基础类,你干嘛呢,用来进行属性资源配置的一个基础类,那它来配置啥玩意儿啊,说了叫resolve处理处理。

Place holder,占位符哪占位符啊,叫bean definition,property values里面的占位符操作,明白这意思吗,那翻译过来啥意思。

你想一下我刚刚定义的这个data source,它是不是一个转成一个BD对象了,BD对象里面是不是有一个东西叫property,Property,里面是不是有一个value value。

里面是不是有一个占位符,你看我意思吗,那是不是意味着,我可以在当前的这个BD对象里面啊,不是这个b post processor对象里面来把这个值完成,整体的替换工作是不是这意思啊。

来我刚刚讲的东西能听懂,同学给老师扣个一,能听明白吗,可以画张图,什么图,这是一个BD对象,但是这个B的对象都保留,就保留原始值,明白意思吧,然后在上面往上走的时候,它会变成一个叫最终的BD对象。

BD啊,指的就是我们的bean definition,这没没没法写了,对方太小好吧,转成BD对象,再转成BD对象,中间这个过程里面,中间过程里面会有一堆的东西能对它进行处理,怎么处理呢。

就是我们刚刚说的叫b factory,Post processor,明白了吗,也就是说在这个环节,它可以对我们的bean definition,对它进行相关的一个处理。

当然这样的bean factory post poor,我可以有一个,我也可以有N多个,这个根据你的实际项目需求来做就可以了,这可以完成一个替换。

当然很多同学老师我不信啊,你信不信,来我们来验证一下,一页看一下,你知道你信不信了,好吧,来举例子说明吧,我不给你们演示,你们可能觉得都听不懂啊,来我找一个代码,我打开一个配置文件来往下看。

在当前配置文件里面,我这是不是占位符,是不是占位符,同学们,没问题吧,全部都是占位符好吧,全部都占位符,我没有做任何值得替换工作,有在中间某个环节的时候,我需要把这些值进行替换,怎么替换来。

我就bug debug的流程啊,同学们,你怎么还有这么老的项目呢,这是我在讲源码的时候重新编译的项目,5。2。9版本的,不是老项目好吧,这讲源码的时候给大家留做的一些案例,不是老项目。

那我们来看我再debug一下,debug之后我说了,刚开始spring一定先有一个容器。

我刚给大家指出来了,这个容器是啥,是default visible bean factory,所以一会我带你看一下这个default lible being factory。

你们可以看看,好吧嗯,启动好了没,因为我这边的是原版那个环境啊,所以它可能每次启动的时候,会相对于比较慢一点,它每次都要重新进行相关的一个编译,而你们如果直接引用战包的话,是不会有这个问题的。

还是比较快的好吧,等一下,怎么这么难,好了进来吧,进来之后来往下走,直接new一个对象吧,好吧,往下走,进来之后,不管他这是个bug,点进去有this往往这边走走走。

点到REFLESH,报REFLESH之后,我刚刚说过了,刚开始上课之前,我就强调了REFLESH它很重要,里面包含了13个方法,如果你想把这个spring框架看连板,那么这13话你是必须要懂的。

如果这13万你不懂,很明显spring你就等于没学会好吧,前面几个步骤我们不看了,我就带你看关键步骤好吧,来到这儿来翻译一下这个名字是什么意思啊,现在我发一下,这是什么意思啊,不对是什么意思啊。

翻译下获得吧,获得新鲜的bean factory对象,也就是说在这个步骤里面,我会创建一个bean factory对象,来装载我们具体后续的bean对象,来点F7进去进来之后有个REFLESH进去。

进去之后,第一步先判断一下有没有工厂,没办法跳过,跳过之后来看这个步骤是啥意思,叫create d factory吧,Create b factory,是不是这意思,我要创建了吗,你点开这个方法之后。

你发现了它里面干了些什么事,来告诉我你有一个什么对象,啥对象不就是刚刚写的吗,叫default lible bean factory,也是我们后面用的容器对象。

都叫default visible bean factory,这玩意我刚刚说过了好吧,所以让你能看到,看到之后,当我创建完对象之后。

我希望你能注意一下这个bean factory,在这里面呢有两个属性值,我希望你能重点留意一下,第一个属性值叫什么呢,叫bean definition names。

第二个属性值叫bean definition Mac,来告诉我,现在我刚刚把这个default liable并value,对象创建成功,他们的默认值都是什么,两个集合嘛,一个HASHMAP。

一个是release,默认的都是什么零八,我现在什么值都没有。

你把这东西记住了,什么值都没有,然后我往下走,走到这一步干嘛的,翻译一下load bean definitions,翻译过来叫什么,叫加载bean对象啊。

been definition对象吗,从这个环节到这儿加载bean definition对象了。

这里面有多少个BEDEFINITION对象,我也不知道,但我们可以往下走一步。

当我走完这个步骤之后,我们可以再打开我们的bean factory,再找到刚刚那两个属性值,你们现在有值了吗。

都是11个吧,是不是已经有值了对吧,那意味着我已经下载成功了,当我加载成功之后,不重要,重要的是什么,我我需要看一下里面的data source。

点开我们这个平台,平时map找到我们的BESOURCE,找到我们的value,找到我们的property values,找到我们的proper value list,找到我们的username来。

你告诉我现在的值是啥,这是什么GDBC用的内容吧。

为啥11个我定义了11个,为啥11个不要问这个问题,我定义了11个,所以是11个好吧,Dd source,我再从这看吧,那已经取消了,我问一下,现在这个值是不是,就是我们从编制文件里面下载回来。

这个值现在替换了吗,没替换啊,没做任何的替换工作,然后我再往下走走走走走走走,走到这个步骤,当我走到这个步骤之后,我为了验证我们这个中间过程里面有没有替换,我们来打开b factory。

再找到我们的应该就是Mac it source,找到我们的value,找到我们的property values,找到我们的这个值,Of your name,我问一下现在值替换了吗,有问题吗,没有啊。

没有做任何的替换工作,没有做任何的替换工作,从来没替换过好吧,然后你翻译一下这个方法叫什么,对方什么意思,别的你可以都不理解,invoke中间分开,invoke什么意思,叫执行或者叫调用,听明白吗。

然后bean factory post processor什么意思,不就是我们刚刚说的那个扩展几点吗,叫bean factory post processor。

也就是说我现在要开始调用执行bean factory post processor,那我们就要看一下。

在这个步骤我执行完成之后,我这个值有没有完成替换,来往下走一步走,做完之后来看一下,听完了没,听完了吗,换了吧,已经换成root了好吧。

下面得判多少了,你换成123456了,1万2也替换了,是不是全部都完成替换工作了,那是不是意味着在这个环节,这我可以完成他的替换工作,来这块听明白,同学给老师扣一,能听懂吗,所以这时候问题来了。

如果你自己需要去替换某一个病,你可以替换吗,听好了,你自己如果想做这件事能做吗,能不能做,可以啊,怎么做,它是一个接口,你只要去实现这个接口,完成你具体的功能不就完了吗,是不是这意思啊,来试一个。

随便写一个,右击new一个class,My bf p p,哎有这东西了,重新建一个吧,无所谓,来右键my BF p p2对吧,在里面实现一下in,post processor实现里面的几个接口。

实验完之后可以干什么事,有一个bean factory的,我可以be factory,第2get bean definition,但是我们有一个person的对象对吧,那这个时候你告诉我。

我能不能获取到现在这个person对象的,Bean definition,能吧,那我获取到对象之后可以干什么事了,person点set,我能不能往里面设置,我是不是想怎么设计,怎么搜,我随便设置了。

只要它里面有的这些方法,我都可以进行属性值的一个基本的设置的工作,这不就完成了吗,对不对,我们现在没需求,没关系,我就是在这打印一句话,比如说ST,应该是0922等于这东西也可以吧,我问一下。

当我定义好一个这玩意儿之后,我们现在容器能够识别到它吗,容器能不能识别到它,能不能,不能你需要把它告诉容器吧,怎么告诉容器啊,第一种方式上面加一个at component,声明好,它是一个并对象对吧。

除了这样方式之外,你可以在我们的配置文件里面,我不是这个,我加一个,So that,并对象,然后打印一个class等于my b f p p2,我是什么样的对象,可以了,帮我生成了对象之后好了,不用管了。

我可以直接来启动我们当前应用程序,我们来看一下它到底会不会打印右击状,我这运行不带debug了,你加注解也可以好吧,注解配置文件两种方式,说什么lock lock了,停掉重来走,哎呀,这有些锁定的文件。

Gradi,5。6。3,Execution history,单调,这里删掉,那句run,这要是没打印出来会不会很尴尬,那肯定会啊,没打印出来肯定会很尴尬啊,肯定会尴尬很尴尬的,但是不可能打印不出来。

好吧,来试试好不好,来我来看092打印出来了吗,对不对,就这玩意吗,好吧,轰隆一问,说spring中BFPP是怎么来实现出来的,注意了,你所需要创建的所有的对象。

所有的对象都会被声明成b definition d对象,所以我可以根据我们BD的类型,来进行一个查找工作,看看工作,这个不是我们这一个重点,我不说了,好吧,好好好,红红,你记住了。

我可以根据我们的类型来识别出,我有哪些必须对象,根据我们的BD来进行对象的创建工作。

所以这块就完成这件事情,就完成这件事情了,这样我问一下,这是只能定义一个,还还还是可以定义很多个呀,这个bean factory post processor,一个还是很多个很多个好吧,你想定义多少个。

定义多少个,那么这么多个怎么执行啊,怎么执行,能执行吗,对它是通过看心情,它是通过for循环来进行执行的,那for循环的时候,我怎么能强调它的优先级呢,比如说我就想让某个先执行怎么办,怎么办。

打锁不用加速,对at order就可以了,at order好,可以指明在当前这样的一个顺序,可以根据我们的顺序来进行相关的一个,执行操作,就这块好吧,当然这是其中的一个步骤,除了这个步骤之外,还有什么。

我这儿再额外补充一些知识,在唉刚刚的东西。

TV派同学给老师扣个一听。

系列 5:P48:48、BeanPostProcessor接口详解 - 马士兵学堂 - BV1E34y1w773

哎刚刚的东西听明白的同学给老师扣个一,你听明白了吗,听完之后我就再补充一个东西啊,在当前这玩意儿在下面它还有一个子接口,我也希望你能够稍微留意一下这个子接口,它其实也非常重要,什么子接口呢。

我写一下叫B,Definition registry,Post processor,你们见过这东西吗,可能很多人没见过这玩意啊,但其实我还是那句话,你通过名字应该能猜出来他到底干嘛的。

叫bean definition registration,不就是注册BD吗,注册BD的一个增强处理器,增强处理器它有用吗,它有用吗,有它的用处非常非常大,它有什么用。

把bean definition装到map中,不太对,怕什么用,在它的下面有一个很重要的实现子类,叫这个东西,原装的这个吗,有人知道这东西吗,卡了的话,重新刷新一下好不好,我不知道你们那为啥总卡。

你们见过这东西吗,叫competition class,Post processor,它是干嘛的,配置类不太准确,他干嘛了,同学们注意了,这玩意儿你要不知道,那么。

spring boot自动装配原理你就别学了,这东西都不知道,spring boot自动装配原理你就别学了,别学了,因为分布的自动装配原理,实现核心点就在于它的一个扩展,明白意思吗,就在这玩意儿。

它很重要,好吧,你能看到一堆的注解的解析过程,看一眼好。

不带你们看一眼啊,我心有不甘,来B。

Registry post processor,这里面有一个方法,点开了实现此类,找到configuration class post processor,在这里面找他,然后我点快点好吧。

你不用管这个步骤了,点它点它点它。

找他来往下看看这个组注释,A process any at property,Source animation,处理这个注解,第二个处理这个注意点,第三个处理import注解。

第四个处理import resource注解,第五个处理艾特定注解,看明白了吗,都是在这以入口能够进来的,如果这东西你搞不明白,那别的东西你就不学了,搜索备原理你永远说不清楚,明白意思吗。

所以这是这块的一个核心点,我们不说这东西了啊,这个这块扯的有点远了,你先把这东西搞清楚了,也就是说我们这儿完成很重要的一个基本功能,那这其实我可以留一个疑问,由于什么疑问,大家想一个问题啊。

你们去你们自己去思考,我今天晚上先摸摸答案,这玩意儿他继承了definition being reject post processor。

那么这里面需不需要实现并factory post processor,里面的方法需要实现吗,看这个继承关系啊,他继承了他,他又继承了他。

他是否需要实现这个里面那个post process bean factory,这个方法需要不需要,一定需要吧,肯定需要,对不对,来公开课同学需要吗要吗,如果要的话,我们可以点开这个东西来看看。

Composition,Composition class,Post post,点开post process,Bean factory,这块有这样的一个实现功能,但里面有一堆的判断逻辑,不管它。

但这块做这样一件事叫enhancer,Configuration classes,这啥意思,别的东西你都可以不了解,Enhanced,了解吧,你看一下什么叫增强,它有什么意义,这里面其实引申出来一个点。

我们在写配置类的时候,pk的时候配置类为什么需要生成代理对象,你考过这件事情吗,配置类,配置类里面你们是那个配置类,是否需要代理对象,需要吗,怎么突然开车没开车呀,需要吗,啊我开车了没有啊,我这看啊。

这个你们是不是因为at configuration过这些类,at configuration类,它是否需要at conversion里面,你们一般会配置一个叫at bean,然后创建出来我们具体对象。

对不对,就是我问一下,这个配置类是否需要动态代理来创建出来,代理对象需要还是不需要,需要吗,要吗为什么呀,有人想过为什么,是什么原因导致我必须要这么做的,核心点就在于这块,好吧,这也告诉你了。

Enhancer,Configuration classes,Enhor,创建代理对象的enhancer,你点进去之后,你会发现里面有具体的逻辑处理过程,你自己看吧好吧,找这个东西你自己看吧。

就里面逻辑里面有这样的一个包含逻辑关系,你们可以自己来看一下好吧,增强肯定要代码吗,不对,这不是更新点,阿福说的靠点边了。

留个疑问下去之后好好思考一下,我们先不管了好吧,有兴趣的话,我们下次再聊,来回过头来看看上面这张图,所以这个图进到这个地方了,也就是说,我现在我现在要把它变成一个最终的对象了,我的值也已经替换完成了。

当我的值替换完成之后,往往下走,走到这块,是不是该创建对象了,创建对象我们说了,我可以直接通过反射的方式,来进行对象的一个创建,那我问一下对象,创建完了之后,下一步干嘛,对象创建完了之后。

下一步干嘛调用使用对该用了,使用使用完了之后呢,销毁,销毁这是不是就是我们整个B的生命周期,从创建开始到使用,从使用开始到销毁这块,我如果把它框起来,框起来,就最后它是什么不就变成十分中心吗。

是不是这意思,但这个生命周期啊太粗糙了,真的太粗糙了,你这样说是不对的,或者说不严谨的,那这样我还要再普及一个最基本的知识,同学们,我们一般说的时候都口头说叫什么叫创建对象,没问题吧,就创建对象。

我问一下创建对象包含几个,过几个步骤啊,对敲黑板要考的,一般情况下包含两个环节,第一个环节叫实例化对吧,第二个环节叫初始化,我先问一下实例化干什么事情,不就是分配内存吗,对吧,当我分配好内存之后。

我的问题是,此时这个对象里面的属性值是什么值,默认值什么问题吧,我们达成共识点,那么很明显,初始化我应该干的事是什么事,什么事属性赋值吧,这大家所有人都想到到此就为止了吗,到此为止了吗,二加属性赋予制。

这是其中一个功能,除了属性赋值之外,还有其他非常重要的核心点,什么点了,比如说执行叫INIT方法,比如说叫扩展实现,还有这样一些东西,这些东西说白了他很麻烦,但是这是spring里面最标准的一套流程。

你是必须要知道的,所以下面我们需要花时间来把整套环节给打通,到底什么叫病的生命周期来,我问一下,有多少同学,现在能把bean的生命周期给完整的背下来有吗,我都不认你们理解啊,你们能背下来就可以。

没有肯定有有很多同学可能会很聪明对吧,上网一搜bean的生命周期对吧,点开网页里面有一堆深究spring变生命周期好吧,别再问spring spring周期了,那随便打开一个帖子好吧,一堆文字来开始干。

开始背对吧,然后呢还有一些同学比较聪明,老师这张图片我去把这张,没了,诶刚刚还有怎么没了,对了大家来看,很多人比较聪明,很多人说老师我去背一张图片,把图片里面的关键步骤给背下来对吧。

告诉一下你背下来之后,你可能每次面试之前你都要去瞅一眼,都要去看看,如果你不看的话,很明显忘了对,很快就忘了,所以这玩意儿你不需要背,写spring源码的作者,他也是个人,他只要是个人。

他就一定会有自己的逻辑思路,那我们能不能把这套逻辑思路给背下来,如果能把这套逻辑思路给背下来,那还有问题吗,这没问题了吗,是不是意思好吧,时间跟他说应该是录播对,没问题,就是录播是录播。

所以下面我们要详细剖析一下,bean的生命周期到底是啥,不是人,别这么说好吧,刚刚我们详细说一下生命周期,从创建对象到使用到销毁,中间还应该包含很多复杂的过程,求道者,你说的加载验证准备解析。

这些东西属于某一某一个bean对象,某一个bean对象的一个创建,但是这个东西它属于JAM里面的,我们不说那么细,我们只是说spring里面大家怎么用的好吧,N9说开发中用不到,注意了,开发中是用不到。

但如果你不会,你可能连开发的机会都没有,所以把这事儿我希望你能想明白,不要说我学东西都是开发商用的,不要用好吧,它就是用来面试的,你说你面试的时候,有谁会问你说你来给我写个代码。

不可能他只能问你这些逻辑上的东西,或者理论原理上的东西,你必须要会,你不会了,你连送CRUD的机会都没有,所以不要再抱怨这件事情了,该学的你就要学,很重要,来我下面带你来梳理这个思路,梳理这个思路。

不要再说老师我是不是不用学,必须要学好吧,第一个不要再说什么内卷什么东西啊,不要说这东西没意义没意义好吧,来我们就学东西就可以了,第一个叫实例化,刚刚说了什么叫实体化来着,NP内存属性为默认值动作。

大家都能理解好吧,在实例化完成之后,下面有很大一块,还要完成一个最基本的初始化功能好吧,初始化到底是干什么事,怎么去理解,第一步你想一件事,我对象创建好了,下一步你告诉我应该干嘛,我们不看源码好吧。

就按照正常的逻辑思路,下一步干嘛,不就该赋值了吗,是不是对应属性赋值啊,随便来一个属性赋值,对不对,我想这个分贝吧,你对象创建好了,下一步直接进行属性赋值,我觉得这个东西作为一个正常人都能想得到。

那复制完了之后,下面干嘛呢,下面干嘛,很多同学可能会比较懵了,老师该干什么事,该扩展了,没到那个环节,也没到那个步骤好吧,他在哪做这个事情呢,你如果看帖子的话,下一步有什么东西,第一个叫实例化变。

第二个叫设置对象属性,第三个叫检查aware相关接口,并设置相关依赖,很多同学对于这个AVA接口理解得非常非常差,来谁能告诉我什么叫AVA接口,这是干嘛的,没听过,你应该听到这啥东西,翻译过来叫什么。

先说翻译过来叫什么,就联想到叫一声到晚啊。

这东西很好理解,我之前给大家讲过不止一遍这玩意儿了啊,讲过很多遍的东西了,它没那么难理解好吧,来随便打下一个对象,我们试一下,把这东西干掉啊,都是之前讲课的时候留个例子删掉,删掉删掉之后。

我们随便创建一个,比如叫student,没问题吧,装好之后我可以往里面写一些属性,Private string name,Private int int id is,这没问题吧,你定义好一个对象之后。

我肯定要设置属性值,我把它设置成自由的,然后生成共有的set和get方法,这没问题吧,来我写这个的扣一,没有人说连这东西都不理解吧,在后续的时候,我肯定要调用我们的set方法方法。

往里面进行一个属性的复制操作,这个我觉得大部分人都能理解对吧,这个基础面向对象好吧。

那下面问题就来了,什么问题,spring本身它是一个容器,它是一个框架,spring里面有没有帮我们定义了很多很多,其他不需要我们用户自定义的对象,有没有,有没有懂吧。

比如说刚刚上面提到的bean factory,这是不是有容器帮我们定义的,再比如说application context,是不是有容器帮我们定义的。

那这个时候问题就来了,同学们什么问题,我这儿完全可以在里面写这样的东西,Private,叫b factory be factory,Private application contest。

嗯contest,是不是数值那一样的,你想吧,我现在已经设置成流量属性值了,它也是私有的,我如果想往当前对象里面,注入对应的一个属性的话,我必须要生成公有的set和get的一个方法,是不是意思是什么了。

那生成好了之后,问题就又来了,同学们什么问题,这什么问题啊,谁在什么时候调用此方法,来先看第一个问题,谁调,你觉得这个赛德法是我们去掉还是容器,帮我们去掉,谁去调,容器吧,你叫对象创建,你都交给容器了。

你自己还没调理方法,你怎么调,你调不了,所以只能是容器帮我们去调用这个方法,放的好吧,第二个问题在什么时候调,什么时候叫,你想吧,这儿有一个set bean factory。

这有一个set application contest,两个set方法,可能还会有其他set方法,我什么时候掉的,我怎么判断启动的时候,启动的时候。

我怎么知道我要去调用这个set in factory呢,我怎么知道我要调用set obligation context呢,因为我是不知道他有几个set方法的,我也不知道里面有什么样的属性值。

那我怎么能确定我去调用什么样的方法呢,听到了吧,所以怎么办,监听实例化没那么复杂,线下面向对象能不能做一件事,D统一的规范接口来实现此功能,通过接口能实现这个功能吗,你就懵逼了。

老师我通过接口定义实现啊,很明显。

来看一下我们的,CSM里面有一个AVA接口,你发现了这个接口跟single ront一样,它里面有任何方法实现吗,没有吧,没任何方法实现,但是此接口它要由子类实现。

比如说像be factory,有个什么名字,什么名字叫set bean factory,你这时候看一下student里面的set bean factory。

和我们这儿写的set in factory一样不一样,这两个方法一样还是不一样,你告诉我。

一样吧,没任何区别,对不对,再比如说再打开一个东西叫application context,Aware。

这接口它也实现了aware接口,它也叫set of ligation contest,是这玩意儿,那你想当我设置好这样一些东西之后,我有不一样,哪不一样,138哪不一样,0879同学哪不一样,一样吧。

那所以我在当前对象实现的时候,我可以写了,怎么写,我能这么做,实现并factory aware逗号实现application contest aware,看了吗,我实现两节课之后,方法都没让我重写。

这直接向上向上指向,向上指向,有了吗,有了吧,这玩意不用两个方法吗。

所以你告诉我我是干嘛的,刚刚说了一个东西叫属性赋值,没毛病,非常对,他就是叫属性赋值,但是他这个属性赋值赋值的是什么属性,什么属性,对象,能不能这么写,叫用户自定义属性赋值,能理解吗,这是第一个步骤。

容器自定义选项赋值,比如说我们的name,比如说我们的是不是这意思,第二个还有个东西叫容器对象是吧,是不是这意思好吧,所以这个步骤合起来都可以称之为什么,这是什么,不就是属性赋值吗。

只不过一个是用户自定义对象属性赋值,一个是程序对象的赋值吗,是不是这意思好,当然有人问了好多同学提出疑问,老师现在是不是都不需要where了,直接auto wear不就行了吗。

好加上艾特auto where也行啊,对没问题,你可以加at auto word,但是如果人就是用插画文件写的呢,你用注解没问题,注解可以填写这件事情,你加一个at oware,如果我不用注解呢。

我可以不用注解吗,我不背怎么办,听到了吗,他是一个标准流程,他不可能预估到说用户他会用什么样的方式,所以我只能说我尽可能的把我所有存在的,可以做的事情,我都帮你去做,就这么简单,你在帮帮不了你了。

我没办法,但我能想到的东西我一定帮你想到这个意思吗,来这块听班同学,到时候扣一能听懂吗,所以偶尔你还能理解吗,能理解吗,好吧,刚刚有人问啊,这是什么软件,这个软件名字叫枫叶云笔记,然后他叫笔记。

你们可以下载好吧,你们可以下载看,容器对象赋值指的是啥,就是指的我们spring整个容器里面,整个容器里面它需要的这些对象,比如说我刚刚写的bean factory。

比如写的application contest,再比如说environment,再比如说resource,loader对吧,这东西全部都是容器,帮我们创建好对象,那这个时候如果我想用的话。

我只能这么干了,我只能通过外接口来实现了,明白意思吧,哦process on,不香了,不是不香了,是那个有九张图片的限制,所以我们不用了,好吧,这个vi接口是空的,有啥用,不就是起一个标识作用吗。

你synchronized也是空的,你怎么实现功能的,是不是这意思好吧,理解同学下去之后,自己好好感受一下,好好悟一下,哪不清楚的话再来问我行吗,来我们这儿画一道横道好,当我们到这个步骤之后。

同学们想一下我完成什么事,听好听好,我的思路好吧,同学们,当我们创建完对象了,我也把对象里面的属性,我几乎都已经复制完成了,我这写个东西啊,我把它对应的那个方法给你们写出来,这个步骤放下。

什么叫create be,这个方法的名字好吧,这个步骤它也有对应的一个方法,怎么显示不出来了,他们叫什么叫populate,B,啊下面这个步骤叫invoke aware methods,好。

它对应每一个步骤里面的方法名称,我给你写出来行吧,来到这个步骤,当你到这个步骤之后,循环依赖明天讲好吧,循环依赖明天讲,大家思考这件事情,当我把这个环节我也做完了之后,下面你在想我该干嘛了,我问一下。

当我到这个步骤,我做完之后,我现在是否获取到了一个完整的并对象,是否获取到一个完整的bean对象,获取到了吗,如果按照我们正常的一个创建对象的逻辑的话,我现在已经实例化完了,我也把属性复制复好了。

那这个对象我是不是应该可以拿过来用了,正常情况我们先不考spring好吧,我们先不考虑spring,就我们如果自己创建一个对象的话,第一步先创建对象,第二步属性赋值,赋完值之后。

我是不是已经拿到一个正常的对象了,这没问题吧,就我们不考虑spring的东西啊,但是在spring里面他还没完,他需要做一堆的增强实现,所以下面做的所有事情都属于什么,都属于并等扩展。

实现了都属于B的扩展,实现什么样的扩展实现,比如说当你这个步骤执行完成之后,下面紧跟着会导入到会进入到一个环节,叫执行前置处理方法好吧,下面还有个东西叫执行后置处理方法,当然很多同学可能不太理解。

这个前置和后置到底代表了什么意思。

很简单,我带你们看代码,打开一个东西叫bean post processor。

终于找到这个接口了,当你打开这个接口之后,你发现了它是不是也是个post processor,是什么增强器吧,它也是个增强器,只不过当前这个增强器它针对的对象是谁,ban吧,是不是ban,所以往下走。

在这里面有两个方法,一个叫post process before an insulation,下面这个东西叫post process after insulation,我问一下后面的单词什么意思。

什么意思叫初始化前置和初始化后置。

那意味着在中间这个环节里面,它必然包含了一个叫初始化的步骤,有点懵逼了,老师你这个大框不就是初始化吗,怎么这还有个初始化,这个初始化跟那个初始化不是同一个东西,一会儿我来解释他们到底是什么样的。

一个逻辑关系,但我们通过方法我们能判断出来这样的东西,而我们这儿说的前置也好,而说的后置也好,它们全部都归属于谁东西,什么东西,归属于啥,是不是叫bean post processor,是不是。

那么有人就会问了,老师这个being post processor,它有什么用处啊,它有什么意义啊,它存在的价值是什么呀,啊很简单,我为什么不上来直接讲AOP,为什么要讲IOC,记住我这说的一句话。

这句话给你写出来,AOP是,I o c,的一个扩展实现,这句话我不知道有多少同学能理解,但是我希望你把这句话给我记住,这句话很重要,其实我们可以来做这样一个判断,怎么判断,先问a OP。

它实现的原理是什么,ABCD是啥,叫动态代理吧,动态代理两种实现方式分别是什么,JDK好吧,或者cg lib这问题吧,这应该属于一个最最最基本的基础知识了好吧,那我现在我已经获取到一个原始对象了。

并对象已经有了对吧,当我有了一个并对项之后,我现在想设置它的代理代理对象,我是不是要把当前对象作为其中的一个引用,给它传递进去,让它来生成我们整个具体的代理对象了。

所以这个时候你如果想判断的话怎么办,找到我们的顶post processor,然后点开里面的实现类,其实你一看,你就能知道哪个是用来生成具体的代理项目,哪个是看类的名字好吧,哪个是第三个。

有没有说第二个的,其实不管第二个还是三个,最终都会找到第三个,当找到第三个之后,我们可以点开这里面的方法,找到我们那个bean post processor里面两个对应的方法。

第一个叫post process before initialization,是这方法点开来告诉我这里面有做任何实践吗,或者说有做任何的额外处理工作吗,有没有做没有,就一个return ban。

把变速箱原封不动的返回去,如果这里面不错的话,我们要看谁了,要看你点开之后,你发现了它里面是有处理逻辑的,在这里面你找一个方法叫Viper if necessary,但如果需要的话。

我就去进行一个包装好吧,你点开这个Viper if necessary,点进去,点了之后往下拉,拉拉拉拉这块来告诉我这个话名字叫什么,创建代理吧,好吧,来再点进去往下翻,最后一行叫propose。

Favorget,Propose,工厂模式,通过代理工厂来创建出来我们的代理对象,所以我还要再接着往里边点,点完之后告诉你了,我要创建a OP的代理了,然后获取我们的代理对象,再点进去,点击之后。

你突然发现了它是一个接口里面的方法,那我一定要找谁找具体的子类实现了,所以我可以点一下子类实现来,你告诉我你看到了什么,什么熟吗,这俩你熟吗,熟不熟,很熟了吧,不就是我通过我的条件判断。

选择一种代理模式来进行对象的代理吗。

所以你想一件事,我们的a OP是不是在中间的某一个环节里面。

去做这样一件事。

系列 5:P49:49、必知必会的13个Bean生命周期处理机制 - 马士兵学堂 - BV1E34y1w773

bean的生命周期里面有没有,有吧,所以这时候你再想想我刚刚说的那句话,我说a OP就是IOC的一个扩展实现,现在这句话能理解了吗,能理解吗,可以了吧,是不是这句话,所以为什么不能先讲AAOP。

他讲不了,很多人问我老师a OP的入口在什么地方,你不把这些东西搞明白,你能知道入口你找不到好,这才是最核心和最关键的点,明白这意思吧好吧,所以这样你明白了,当然如果你想去研究的话。

你可以点开我们的bean that being post processor,在这个being post processor里面。

它依然有一堆的子类实现,你可以详细去研究很多啊,我们也可以自定义,你看你的需求,明白意思吧,这里面都是子类,先把它关键的核心点先掌握到,找到之后再说别的好吧,来接着往下走,再往下走的话到哪了。

到这个初始化的步骤了,这块难理解了,老师这个最外层叫初始化,里面还有个初始化,这个其实翻译成初始化不太严谨,它更严格,应该叫什么叫执行初始化调用方法,这样能理解吗,什么叫执行初始化调用方法。

比如说我随便打开一个配置文件吗,我在定义好一个bean对象之后好吧,这后面可以加一个属性叫init method,见过这东西吧,当然这东西我们一般是不写的,一般是不写的,但如果你写了。

我是不是要知道这些步骤是干嘛的,这些不都有意义吗,没啥意义,在java语言里面其实没啥意义,如果你接触过Python,你这东西应该比较熟,Python里面有两个很重要的方法,第一个叫下划线。

下划线new它相当于java里面的构造方法,还有一个叫下划线相关相应INIT它是干嘛的,完成初始化方法,这里面是不是就完成了一个最基本的属性,复制工作,而我们的属性赋值,不好意思。

我在上面环节我已经完成了,所以这个初始方法你可以调也可以不掉,看你的心情,听明白了吗,K掉也可以不掉,没关系的,但是好吧,这它是有自己存在的意义和价值的,因为在当前这个方法名称叫什么呢。

叫invoke init methods,在当前这个方法里面,它有一个非常牛逼且神奇的判断逻辑,什么逻辑呢,它会检测一下你当前这个病对象什么叫是否,是否实现了,IALIZINGB接口好了。

又来了一个接口,我如果直接写这个接口,你知道是干嘛的吗,你们知道不,这叫干嘛的,很大可能没见过,可能不知道,但是你一定见过一个方法,你一定见过一个方法,什么方法叫after。

property set能见的方法吗,见过没,别告诉我没见过啊,你们你们如果在公司没有框架的话,别的代码里面一定写过这样的东西,不可能没写过,这样的东西是一定写过的,已经学过的这啥呀,很多同学懵逼了。

老师这啥呀,我好像没怎么见过这玩意儿,他干嘛的,他干嘛使的,有什么用处,忘了尴尬一点都不尴尬。

忘了没事好吧,我知道你们会忘了,工作中不用嘛,肯定会忘了吗,来你在这后面加一个接口,你是不是来自定,这里面需要实现一个after property set的方法,你告诉我在这个方法里面可以干嘛。

去干什么事,这里面我是这么理解的,叫给用户最后一次机会,机会来进行赋值或调用操作,这边能干干这件事,this点name等于张三,可以这么写吗,可以吧,是不是在bean创建完成之后。

我是不是可以最后再执行这个操作了,是不是给用户一个机会,因为你整个容器的框架的整个对象创建过程,全部都交给了spring来控制这个环境,我们是干预不了的,没事我可以干预,我给你留个口子。

在这儿我来干预一下,在最后一个步骤的时候,我来干预一下,行不行,可以吗,可以吧,这就是这个方法它存在的意义和价值。

所以它也相当于做这样一件事,当然这样做完之后,下面还有一个叫否,如果我不做的话怎么办,开始调用invoke,Init method,这块调我们最基本的这个初始化方法就可以了,但前面我还可以在属性。

对属性做最后一步的复制操作,这会连过来,明白意思吗,就是这个房间里面我要做的一些最基本的工作,下来下来下来,当这些步骤我全部都执行完了之后,告诉我现在干嘛了,干什么事,现在不就开始使用对象吗,对吧。

当对象使用完了之后,下一个步骤就是销毁对象吗,是不是这意思,现在理解了吗,来刚刚那个环节能理解同学给老师扣波一吧,销毁一般是不会问的,为什么什么时候会销毁对象,你在关闭容器的时候会销毁对象。

你有自己关闭过容器吗,同学们,你有自己关过容器吗。

从来没有,你们每次停怎么停,我点这个插口点了,你没管过,我们就通器,所以不用管它啊。

面试的时候这块也不会重点问的,也不是重点问的,明白意思吧,好吧,来这儿又会有一个问题,刚刚很多同学都提到了一个几个点,老师你在刚刚讲解过程中扫环节了,扫什么,有这个东西,Post construct。

还有一个at pray destroy,对吧,有两个方法来我问一下第一个注解,第二个注解不看了好吧,第二注解不问第一个注解有什么意义,谁能告诉我,探索用处,没用过很多人,刚刚很多人刚刚跟我说。

老师这个注解什么时候处理的,它相当于做的事情叫什么,就是执行,初始化方法,好吧,那么问题来了,它执行初始方法,大家想好啊,我刚刚给你画的这张图是整个bean的生命周期,叫整个bean的生命周期。

那在整个bean生命周期的时候,我用了这样一个注解之后,他那个对象是否要经历这样一个,完整的bean的生命周期,要还是不要,要吧,那如果我想加这样的功能,它应该在哪在哪实现啊,你告诉我在哪实现。

哪能实现你猜你猜他,哪能实现每一个步骤都给你画出来,哪能实现,你告诉我,哪能,隐匿他引的流,给你扩展点了吗,after process里面给刘伟,你扩展点了吗,我就说你们听课就是听课。

你们不会去思考,来找一个东西,同学们看好啊,我带你们找关闭掉。

找到一个接口叫B,post processor来在这里面找算了。

我们换一个方式吧,我不用这个东西,我先不问这个啊,我换一个注解,这样锥子能实现的,这俩注解在哪实现的,这个用的多吧,你这俩用的不多,我忍了,这都用多吧,他在哪掉的,在哪掉,哪会掉,同学们想明白一件事。

初始化调用,你初始化这个步骤太多了好吧,同学们想明白一件事,先有的注解还是先有的XM,对不对,就是我刚开始使用框架,发明之初的时候,我现有的XM,当我只有XML的时候,我一定已经开发出来一套标准的。

bean的生命周期流程对不对,现在我发明出来一个东西叫注解,我需要把注解的功能也怎么样完成注解的功能,那这就会有一个选择,什么选择上面已经是一套比较规范,比较完整的一个流程了。

那这块我是要推翻重来还是扩展实现,告诉我一定是扩展嘛,对不对,那你就要想在整个生命周期这个环境里面,哪给我们预留了扩展的点,哪扩展了,不就是bean post processor吗,所以你打开这个接口。

找到它的实现类,找哪个,刚开始学,挨个去找,如果有经验的话,往这儿看这个东西叫什么,你翻译名字告诉我叫什么,叫all word annotation,Being post processor。

完成什么功能,你告诉我,是不是这样,往下找往下找往下找找找找找来,你告诉我你看到了什么注解,什么注解叫auto wear value,这俩不就是注解吗,是不是注解,这不就是value这个注解吗。

看没意思了吗,是不是这意思那一样的,我想实行小学那个post construct,这个东西在哪找啊,也是找子类实现吧,整体子类实现它完成了一个初始化的功能,以它配对的还有一个叫pre destroy。

不就是初始化和销毁吗,那对应过来叫什么,不要找名字了,你如果找PRE,你是找不到的好,它叫什么呢,叫这玩意儿,叫init destroy,Annotation,Bean,Post processor。

好吧,往下找找它的一个实现子类,在这里面有一个对应的注解,来你告诉我你看到了什么,post construct和pre destroy能看到东西吗,看到了吗,就这就这就是这些注解来这块能看明白的。

同学给老师扣一,能看懂吗,没问题吧,这不是他现的过程吗,就要尝试去找嘛,当然这一块在实现的时候,他还有点不一样,为啥不一样,这个这个这个接口叫extension aware。

Being post processor,它继承了being post processor,明白意思吗,明白意思吗,也就是说他们调用的时机,跟我们刚刚说的不太一样,但是它一定归属于谁。

叫being post processor,因为being post processor下面它依然有一堆的接口,子接口子类接口,比如说我刚刚说的instance aware。

Being post processor,除此之外,还有什么,有人见过那叫smart,这叫smart,叫merged bean definition post processor。

还有个东西叫smart extension aware post processor,看完意思吗,它里面的父子的继承关系依然是异常复杂的,你如果在子类里面找不到,就要去父类里面找好吧。

找到具体的一个逻辑实现,然后来进行相关方法的一个基本调动工作。

好吧,这东西不聊了,好吧好了,刚刚我把bean的生命周期给大家讲完了,来听白同学有点扣,波,一看看能懂吗,具体的实现逻辑,我需要一行代码,一行代码带你bug才没时间了好吧,我带你们过这东西了。

来回过头来打开我的PPT来,我们回顾一下这几个东西,第一个IOC的容器的核心实验原理,这东西我刚带你画图了,能不能记下来,能记下来吗,没问题吧,还是一样,从应用去入手,然后去想它的脉络是什么样子的。

然后一步步去往下走,脉络很重要,第二个bean factory post processor接口详情详解,扩展干嘛的,你就记住它能完成对BD对象的扩展就完事了。

第三个叫bean post processor接口的详解,他应该对bean对象来进行扩展,第四个叫13个bean生命周期处理机制,13个哪来的,是我从图里面一共13个步骤。

刚刚我已经把关键的这些步骤都给你们说掉了,除了这东西没说,这后面两个东西没说,这是销毁的东西,我没聊,这是销毁环节要做的事情,我们跟你们说,其他关键步骤,我基本上都给大家讲到了,好。

这是你们应该进行相关的一个处理,或者说了解的一些核心点对吧,然后再往下看,下面还有叫spring aware接口的意义,我觉得这东西会了吧。

哎最后还有一个叫bean factory和factory bean接口的对比,来先说这俩东西,谁能告诉我并非和犯罪并有什么区别,面试中有人被问到过这个问题,被问过这个问同学给老师扣个一,有人被到过吗。

没有啊,一次都没有啊,我觉得应该有人被问到过,同学们注意一件事,他们俩的区别,想聊区别,先聊共同点,他们俩共同点是什么,都是记住啊,都是用来创建对象的,我希望你能把这件事搞明白,都是用来创建对象的。

这是最关键的一个核心点,好吧,那不同点是什么,不同点在于这东西bean factory不是factory bean,它里面包含了三个方法,第一个方法叫is singleton,干嘛的。

判断是否是单例对象,第二个get obje,Tap,找获取对象类型,第三个叫get object是干嘛的,用户可以按照自己任意的方式来创建,对象,不是什么特殊对象,没有特殊对象,这一说就相当于什么事。

我们的bean factory,刚刚我在你看过流程了,你们觉得bean factory那套流程麻烦不麻烦,bean factory那个bean的生命周期要完整,流程麻烦还是不麻烦,我只在你画了一个图。

还没到细节呢,细节的时候更麻烦,它包含了非常非常多的一些异常琐碎的步骤,所以它是一个非常麻烦的东西,但是它是一个标准化的东西,标准化流程明白了吗,要说对象创建的时候,如果你没做任何特殊声明的话。

它就是一个标准化流程,而下面这东西是什么意思,什么东西叫私人定制,我把上面称之为叫流水线,下面叫私人定制,什么叫私人定制,你在这个get object这个方法里面,你可以使用new的方式创建对象。

你可以使用动态代理的方式创建对象,你可以通过反射的方式创建对象,你自己开心就好,你想怎么创建就怎么创建,最终我只要能够获取到一个对象可以了,它不需要经过spring定生命周期。

这一系列非常异常麻烦的流程,就按照标准就按照你自定义方式走就可以了,就是他们两个之间的区别就这样,有什么区别,没啥区别,就这点好,一个是流水线,一个是自然定制,就这么简单。

就这么简单好有说老师这东西怎么用啊。

很简单来定义一个是不是写过这东西啊,找一下factory bean,我找一下,我忘了之前有写过这东西,算了直接写一个吧,有一个,可以吧,定好之后,实现一个接口factory bean,这样的。

还有一个方法return true,这样get到BT就写student加class,这边该怎么写,student s等于另一个student return s,可以不完了没了,同学们就这么简单。

你可以这么干嘛,你也可以怎么办,你可以怎么做,Property,第2new propersistence对吧,student点class,Get class,Loader,Student。

The class get interface,又一个ination handler能不能写,我在里面是不是也可以写,写逻辑,写逻辑之后,我是不是获取到一个方法了,一个对象吧,我能买个对象,是不是你的。

对不对,袁老师,那我定义好这样一个东西之后,我怎么来让他进行一个识别呢,怎么识别能识别吗,能识别不,啊那能不能识别艾特,这哪有地方让你用at be,怎么做,同学们一看你就没看过核心什么input。

不需要那么麻烦好吧,注意了,当你在生成每一个具体的对象的时候,它有一个标准的bean对象的一个配置流程。

这里有个reflex方法,点开它,在这里面我会获取到当前的bean要创建的名称,我开始循环遍历名称,获取它的BD对象,当我获取到BD对象之后,第一个步骤是什么意思,你告诉我第一步是什么意思,告诉我。

啥意思,叫is factory bean,判断一下你到底是否是factory bean的一个子类实现,如果是的话,我用前缀加上命名称来进行相关的一个获取,获取完成之后在里面进行相关的一个判断。

在这里面的步骤里面,有一个东西会调用到get object这个方法,然后我把我的对象直接就创建出来了,听到了吧,每一个步骤进行判断的时候,都会先判断一下你的病是不是一个factor be,都会挨个判断。

因为这是一个循环,每一个对象都会经历这个环节,所以你告诉我能不能识别,能不能,哎能不能啊,大哥们可以吗,好吧,所以你看一下这个流程,你看完流程之后,你就不用我讲,你就自己熟悉了。

所以这才是最关键且最最核心的点。

OK好了,这是今天晚上给大家分享东西来,有收获的同学给老师扣波六,你说过吗,这东西有收获了啊,你只是把这一点东西看完了,看出来了,可能你达到你的目的了,但是没达到我想要的目的,我刚刚带你看了一堆东西。

一堆东西,我想问一下,我们该总结了总结什么源码的方法论,我还是那句话,我只带你看那点东西,你只是把这一个流程看清楚了不够,你要掌握看源码的方法,这才是我最想教给你的东西,你如果看方法不懂的话。

这东西白扯换了,spring下来怎么办啊,明白意思了吗,好吧,怎么办,怎么选,刚刚我给你讲那东西,我怎么给你讲的,过眼云烟,第一个很重要的核心点是什么,注意的,不要忽略源码中的注释。

我刚刚带你们看了多少注释,你不要把注释看了之后,当没看到直接跳过去了,不要这样,一定要看注释,原版里面并不是说我每一行我都给你写注释了,它不是这个样子的,它只在关键且核心的步骤里面帮你写注释了。

所以那个不注释不是我的中文注释。

好吧,我不是说我的中文注释,我说的这些英文注释,这英文注释不是这中文,中文是我自己配的,我说的是英文注释,这里面会给你很多的思路报道,刚刚那你看这看接口的时候很重要很重要好吧。

还有吗,第二个,我刚刚有提到设计模式吗,同学们,我刚刚是听到了设计模式吗,说的好像我能看到英文注释一样,连英文注释你都不想看的话就没辙了,不要在意细节,要先梳理脉络再抠细节,这事很重要,什么意思。

你不要上来之后,每一个方法都想点进去看一眼,我怎么那么欠呢,不要这样哦,你如果每个方法都给你看一眼,一会儿你就焦虑了,甚至你都看到最后,你都不知道自己为什么进来看的,我为什么要进来看,一脸懵逼。

听到了吗,所以你看到这个方法之后,大概能猜出什么意思就可以了,所以紧接着下一点是什么叫大胆猜测,小心验证,谁也不是原版的作者,谁也不知道他怎么想的,你管他怎么想的,跟你有什么关系啊,对不对。

所以你去猜嘛,我刚刚一直问,你来告诉我这个方法什么意思,我是不是问过这句话,为什么你这话呀,你看见名字之后,你就能大概猜到这个方法要干什么事,要处理什么逻辑,它命名非常规范,所以你根据这些规范的命名。

你就能猜出来他到底是干什么事的,然后再猜再验证不就完了吗,如果猜错了,你又不会掉音肉,猜对了,你是不是还很开心,是不是这意思好吧,来第五个还有什么,一直有人说老师我英文能力太差了,怎么怎么样。

都21世纪了,英文差还叫事好吧,使用插件对吧,来告诉你们它叫什么,叫translate。

就这玩意translate,我我英文也不好,你看我读单词的时候不敢给你们读,我都怂,我都害怕又怎么样呢,我有插件翻译啊,实体化之前的单例对不对,随便选一个over翻译在是不是这意思。

怎么这人还能不一定能给难住了,不存在好吧,OK所以善用插件,当然最最重要的是第六点,就坚持看,坚持看坚持看,所以咱们同学有很多同学,我问一下,有多少同学在我讲源码之前看过源码,给老师扣一有吗。

我觉得一定有很多人看过,但是一定有很多人没坚持下来,为什么,接下来就我说的方法不对,就是方法不对,你掌握方法了,这事就很重要,找方法就能看下去,你接着看下去的原因是什么,我一直给大家举个例子。

我说你想一件事,你想想你大学的时候,你考四六级的时候,你干什么事,你买了一本单词书,你背了4年,你告诉我,你还记得几个大学的英语四级单词,单词书,你记住几个,你告诉我啊。

记住几个就记住一个单词叫abandon,其他东西都没记住啊,是不是这意思,你每次都从头来从头来从头来,那还可行,每次都从第一个点开始来,第一个单词开始背,每次都从第一个单词开始背,你只记住第一个单词吗。

现在都记不住吗,而第一个单词还非常尴尬,告诉你要放弃,你放弃得了,是不是意思,所以你记住了,你先捋出一个脉络图出来,当你把这条脉络图捋出来之后,你再去一步扣细节,我今天我就看XML文件解析。

明天我就看注解的解析,后天我就看B对象怎么封装的,大后天我就看in factory post processor,大,大后天我就看他创建对象,再往后就看使用,再往后就看销毁你一天,看见你往后走。

你中间留个疑问,能不能记下来,明白了吗,记下来就完了吗,啊刚刚有人还说老师这东西第七点叫天赋,你说看看源码需要啥天赋,他有啥天赋,他不需要天赋,他就看你能不能学下去,有啥天赋,你告诉我。

而且我说的一定对的吗,我说的只是我的理解,我的理解是不一定完全正确,但是我能够自圆其说,并且让你们理解他就这么干的,是不是这个意思,你话怎么说来着,1000人心中有1000个哈姆雷特,就这意思。

每个人看原版的时候都能理解到不同的想法,你可能比我还优秀,但是你有没有去干这件事情。

如果你去干这些事情了。

系列 5:P50:50、循环依赖问题 - 马士兵学堂 - BV1E34y1w773

来先说明一下到底什么叫做循环依赖,这东西啊也比较简单,什么叫循环依赖啊,我们都知道在spring中,对象的创建是交给容器框架来执行的,那么ban是默认是单例的还是圆形的,单例吧。

也就是说在整个容器框架里面,对象有且仅有一个,那么这个时候就可能会存在一种情况,我这里面有一个对象是AA对,象里面呢有一个B属性对吧,同时我还有一个B对象,当我在进行这两个对象赋值的时候。

就会产生循环依赖问题,那到底是如何产生的呢,其实也非常简单,你想吧,现在我的容器里面有两个对象,不管先创建A还是先创建B,总之我是要先创建一个对象的,我们可以举一个假设,假设我先创建的是A对象。

如果我先创建A对象的话,你想吧先进行A对象的实例化,当实例化完成之后,我要给A对象里面的B属性进行赋值操作了,那我问一下我在赋值的时候,我有B对象吗,刚开始肯定没创建B对象,所以我开始创建B对象了。

当我创建完B对象之后,我要给B对象进行A属性赋值了,那么这个时候A是不是也没创建完成,所以它就变成了一个链式的结构,也就是说变成了一个闭环,当形成这个闭环的时候,它就形成了一套循环依赖。

也就是说我们循环引用这个过程,这个时候程序就会报错,告诉我们说程序继续执行下去了,我们要想办法让程序能执行下去啊,这是我们循环依赖,最直接或者最简单的一个例子,当然有人说老师如果是三个对象,四个对象。

五个对象呢,不管你有多少对象,整体的逻辑都是这个样子的,所以这点大家没必要有任何的一个疑惑,然后呢,今天的课程是跟昨天的课程相关联的,我昨天在讲spring的IOC的时候,我就说了。

ban的生命周期里面,包含了N多个环节和N多个步骤,那我问一下,在那些环节和步骤里面最主要的是什么,是不是两个字,是不是有两个名词,第二个名词叫做实例化,第二个名词叫做初始化吧。

所以我们完全可以以一种画图的方式,来模拟一下,这个循环依赖问题到底是如何产生的,这个图只是一个最基本的简略图,它不足以表达我们在实际情况里面,要存在的情况,那怎么来创建这件事情啊,很简单。

第一件事我说了,比如说先创建就创建创建A对象,这没问题吧,当我创建A对象的时候,同学们,你想下一步该干嘛了,如果你想创建A,必然是涉及到一个实例化的过程,所以紧跟着后面一个步骤是啥啥东西,你们来说好吧。

不要让我来说啥玩意儿,啊实例化吧,你说实例化A对象,当实例化完成之后,我想问的是,此时里面的B属性等于什么,那么肯定是默认值嘛,刚开始等于是空的,然后当这步完成之后,紧跟着下一步我要做一个操作叫初始化。

A对象,那说白了什么叫初始化对象,不就是给B属性,赋值吗,是不是逻辑给B属性赋值,而在赋值的时候,我们都知道容器里面对象默认是单例的,所以为了查,为了得到我们的B对象,那你告诉我下一个步骤我应该干嘛。

是不是紧跟着应该是去叫从容器中打的,是不是从容器中查找B对象吧,是不是查找比对象,我要找到吗,如果这既然是查找了,意味着一定涉及到两个结果,第一个找到了,第二个没找到,我们先说如果找到了找到。

抓到之后怎么办,是不是直接赋值即可对吧,他直接给我们当前这个对象赋值连过来结束了,那很多情况下是什么,是没找到吧,所以这有一个问题就是没找到,如果没找到怎么办,我是不是该创建B对象了,一定要创建吧。

你不创建的话,这个步骤是没法做的,所以该创建B对象了,这在这能理解的来,能跟上的,给老师扣个一,能跟上不,这没问题吧,最基本的一个环节,然后下面当创建B对象之后,跟刚刚的流程是一模一样的。

这步骤叫实例化,实例化,B对象对吧,然后呢,此时A等于空,那下面再次做这个操作的时候,紧跟着后面就开始叫初始化,B对象说白了就是给A属性赋值,那同样的当我在给A属性赋值的时候。

我是不是一样要去容器里面查找,我们当前的A对象了,所以这一样拿过来容器中查找A对象,当我在进行查找的时候,也百分之百会需要一个东西,或者存在两个结果,要不然你找到了,要不然你没找到,就是两个来。

先说右边右边这块儿,如果我找到了,抓住怎么办,是不是说了就直接赋值即可,然后呢下面这连下来结束,那下面的呢如果没找到,我是不是又开始进行整个A对象的创建了,来这个流程或者这个过程能看懂吗,这没问题吧。

没对齐是吧,就这样吧,无所谓啊,这没问题吧,来你看一下,当前这个图里面还有没有一个闭环存在,一定有吧,从创建A对象开始到往后走,它形成了一个闭环,那我问一下,当前闭环存在的原因到底是因为什么。

谁能告诉我,那为什么存在这样一个闭环,在闭环形成的时候,中间必然包含了一个非常重要的核心步骤,就在于这块,如果这个地方,如果这个地方我找到A对象了,我是不是就不会有闭环了,或者换句话说。

如果我能把这个东西给阻断掉,它还有闭环吗,这就没有了,所以当它形成这样的一个闭环套路之后,我们就要去思考一件事了,思考什么事情,我能否把当前的闭环给它解开,不要让它变成一个圈。

因为你变成一个圈之后都很麻烦啊,他一直一直这样走,你又想我怎么做这件事情还是一样,注意你在找闭环的突破口的时候,先从哪开始找,从最后一个步骤形成闭环的这个步骤开始,从这开始这个环节明白意思吧。

这样大家一定要注意了,那我问一下,当我这儿开始查找A对象的时候,在刚刚整个创建流程里面,我的A对象到底有没有创建,有没有,听完这个问题啊,在这块我在查找的时候,我的A对象到底有没有创建,有说没有。

有说有创建了吗,这白字白纸黑字写的明明清清白白的,就是创建对象吧,我其实已经有一个A对象了,只不过当前这个A对象,不是我们传统意义上的A对象,啥意思,对象在创建过程中,它存在了两种状态,好亮状态。

怎样状态,第一种状态叫做完成实例化且完成初始化,这个时候我们给它一个名词,比如说叫成品对象问题吧,那一样的我可以再换一个叫完成实例化啊,但未完成初始化,我们把它称之为另一个名词叫半成品。

半成品对象这样东西能理解吗,看看这过程,这两个成品和半成品能理解的,扣个一就可以理解吧对吧,这就是说我在对象的时候,两个不同的状态到底是什么东西,那你想一件事,当我最后一步在形成这个闭环的时候。

我现在的A对象它属于成品还是属于半成品,什么叫半成品,半成品吧,对不对,半成品,那紧跟着就会有一个问题和一个步骤来,有一个问题等大家什么问题,如果我持有了某一个对象的引用,那么能否在后续的步骤中。

给当前对象进行赋值操作,能还是不能听完这个问题啊,这个问题才是最关键的核心点和最本质的东西,如果我持有了某一个对象的引用,那么我能否在后续的某一个步骤中,给当前对象进行复制操作,可以吧,你有了应用之后。

有了引用之后,我能知道他对象的地址,那我一定能够对它进行相关的一个复制操作,所以肯定是可以的,如果这个步骤可以的话,那我们就要去思考一件事情了,什么事情,这个步骤我要去查找A对象。

我虽然获取不到完整的A对象,但是我是能够获取到半成品的A对象了,这肯定没问题吧,所以是不是相当于我们可以把这个步骤给干掉,也就是说它是不存在的,不存在的话,也就意味着我们在刚刚上面整个查找的环节。

或者过程中,我要加一个东西,加什么,就是大家说的加缓存,这玩意儿好吧,加缓存这玩意儿怎么加呢,没有半成品啥意思,完成了实例化,但没有完成初始化吗,我昨天不是讲IOC的时候。

不把大家给大家讲了一下bean的生命周期吗,在bean的生命周期里面,是不是分了大概的分几个模块,实例化对吧,初始化,然后又分为使用中,然后属于销毁,是不是四个状态。

然后我们初始化里面又包含了很多个步骤,我们把这东西统一来说了,统一来说了好吧,同学描述了,所以这时候你想当,我还是沿着这条链路来走的时候,我实例化完A对象之后,我能不能把当前这个A对象。

把它放放到某一个空间里面去啊,举例子,我这儿放一个结构,放啥呢,放一个map结构,我把这个map称之为缓存,可以吧,每次当我存储完具体的一个对象之后,我创建了一个对象之后。

我先把当前的A对象放到缓存里面,那现在我的问题是,现在位移缓存对象里面的A它是什么状态,什么状态,半成品状态吧,记住啊,半成品状态记住它,然后往后面接着走,当我走到这个环节的时候。

叫初始化A对象里面的B属性,也就是说我给B属性要进行复制操作了,我一定从中心点查到B,查到B的时候,我能不能去当前的缓存里面找一下,可以吧,我从缓存里面找B的时候,你告诉我我能找到B对象吗,找不到吧。

因为他还没开始创建嘛,所以一定找不到,找不到,我再接着往下走,我开始创建B对象,当我的B对象创建完成之后好了,这叫实例化B对象吗,我能不能把我的B对象,也扔到当前的环境里面去,可以吧。

此时我的B对象它也是什么状态,叫半成品状态都是半成品,不管它都是半成品,然后我现在给B对象里面的A属性赋值,我这儿从容器里面找的时候,我能不能从当前缓存里面也找一份,这肯定没问题吧。

我在找这个A对象的时候,你告诉我这里面现在有没有A对象,有吧一定是有的,我是有一个对象,当我这有对象之后,是不是意味着我已经找到当前的A对象了,哪怕你现在的A对象,它就是一个半成品,也没关系。

我就是能找到它,我只能找到他,找到之后,我把刚刚的半成品对象我赋值给B属性,那我问一下啊,当我这个地方我找到我们的A对象了,当我这找到之后,现在我的B是什么状态,什状态B是不是已经变成一个成品了。

它依然是一个半成品,就相当于我持有了当前A对A对象的,什么引用吧,我在后面的时候我再给它完成赋值操作,是不是意思,所以现在B已经变成一个成品对象了,那我现在我B的成品要不要往缓存里面放,没问题啊。

要不要往管子里面放,不用啊,不要你后面怎么找啊,要吧,就意味着这会存在这样的东西,叫B冒号成品,是不是意思,这没问题吧,叫B叫成品,接过来,然后我这放进去之后,下面紧跟着回到这个环节里面。

现在如果我再去我们的容器里面,查找B对象的时候,我能不能找到B对象,先留着好吧,我们先写先留着,先写到这,先写到这,这能不能获取到,能吧好吧,那你想我这应该取的是B的半成品。

还是取的B的成品去办成那样的成品,你有成品了,我肯定取成品对象嘛对吧,所以这个时候我找到B的成品对象,当我找到之后,我给A里面的B属性来赋值操作,那我问一下,现在我们的A对象它属于什么,属于什么东西。

成品了吧,A也是成品了,对不对,所以我把A我也写进来,A,冒号成品,同学们,你想一件事,当刚刚这个流程我总体都完成之后,我有没有解决刚刚我所说的循环依赖问题,你先不考虑缓存里面这个半成品和成品的事。

好吧,解决了吗,是不是解决了,这就是spring中到底是如何解决循环依赖问题的,但这里面还有问题,因为我这边写的时候,现在刚刚在写的时候,同学们都发现问题了,老师当你形成了一个成品的A和B对象之后。

我不会对这玩意儿进行覆盖吗,为什么你这个缓存里面它既存在了ab的半成品,又存在了ab的成品对象,这很明显不太合适,是不是不太合适,那我怎么办,所以大家就要考虑一件事了,这个map到底是啥玩意儿。

而据我们刚刚这个流程,听明白的同学给老师扣个一,我看看,没问题吧,我把这个框一下换个色,来看一下,这流程我觉得听懂应该没问题吧,说听懂没问题好吧,只不过对于这个Mac这大家还有疑问,那么这还有疑问。

所以我们之前按照我不讲这节课之前,你们的理解怎么解决循环依赖问题的,Spring,如何解决循环依赖问题的,基本上所有看过帖子和面试中,被问到过题的同学都会搭一个东西叫三级缓存,当然还有同学会说一句话。

叫什么叫提前暴露对象,是不是意思就是说通过这样的方式来解决,这没问题吧,但是你注意了,其实它解决循环依赖的问题,最根本的点在于什么地方,在于一个东西,记住了,叫实例化和初始化分开来操作。

我们刚刚能划开这样的一张图,是因为我把实例化和初始化的步骤是分开了,正因为分开了,所以你才能完成这样一件事,那我问一下,有人见过spring的三级缓存到底是什么东西吗,或者到底长什么样子吗,有人见过吗。

三级缓存到底啥玩意,很多同学光在说三级缓存,三级缓存是哈希map还是看看哈,希map还是map。

来我带你们看一下好吧,在spring源码中有一个类。

我希望你能记住叫default呃,Singleton。

Being reject,在当前对象里面有三个缓存结构。

分别是这玩意儿。

我把这三样东西拿出来粘出来。

14段粘过来,我给你们放到这把三东西拿过来。

这就是spring里面的三级缓存,好吧,来解释一下三级缓存分别是啥东西,比如说第一个像这块singleton objects,它称之为叫一级缓存。

需要把字改一下颜色。

这么说的,一级缓存就这玩意儿好吧,同样的还有二级缓存是这东西,这叫二级缓存啊,那一样的,还有三级缓存,就是中间那块儿它叫做三级缓存,我希望同学们能明白一件事,这里面所说的一级也好,二级也好,三级也好。

是人为给它下的一个定义,他在他这个三个map定义的时候,并没有明确说明说那哪个是一级,哪个是二级,哪个是三级,这种人为给它加上这样一个东西,好吧,那这个时候我的问题就来了,同学们什么问题。

这三个缓存它们有什么样的区别,有区别不,来有区别吗,有吧什么区别,语文老师他们有的是contact hashmap,像一级和二级都是content hashmap,而三级变成了HASHMAP。

还有它们的容量是不一样的,上面是256,一级缓存,256,二级和三级是16,还有吗,除了value这些这些东西不一样之外,还有什么不一样,其实三个缓存里面最最最最大的一个区别,并不在于后面这块东西。

他只是为了控制线程是否安全的,最根本的点在于泛型,我希望你能够好好看一下这个泛型,一级缓存和二级缓存里面,我放的全部都是object类型的对象,就是一个对象吧。

但是我的三级缓存里面放了什么叫object factory,这个object factory到底是啥东西,你们知道吗,啥玩意儿,记住它叫做函数式接口,函数式接口不是工厂对象好吧,不要直译,不要直译。

千万不要直译好吧,它叫做函数式接口,你可以理解为它可以把什么,把匿名内部类和lambda表达式传递,进去当做参数,好我们来看一下。

找到一个对象,Object batter,上面写的东西叫functional interface,叫函数式接口,如果谁不了解什么叫函数式接口,同学好吧,下去之后好好看一下JDK1。8之后的新特性。

这属于一个新特性,其实也没有什么难理解的啊,就算函数接口,那它有哪些用途呢,就是我们可以传递一个匿名内部类,或者传递一个拉姆达表达式进去,相当于是一种函数式编程了,我问一下。

在原生的java jdk里面或者java里面,我能传一个函数当做参数吗,能不能不能吧,但是当你有了函数式接口之后,它可以定义一个函数式接口的参数类型,然后我可以把拉姆达式传进去,而我在进行调用的时候。

可以通过get object来进行相关的调用,就这意思,比如你写的函数接口,括号指向再写一个create d,假如你写这样一个方法,当写方法之后,它就变成一个函数接口,我传到三路里面去了。

当我在调get object方法的时候,实际上调的就是create bean这个方法啊,这属于一个最基本的一个应用。

好吧,如果谁这块不熟的话,你先去看一下。

系列 5:P51:51、源码留心的6个方法 - 马士兵学堂 - BV1E34y1w773

好吧,调用的时候通过get object方法来调用,把这两句话我希望你能够记住了,我希望你能记住好吧,那光讲这东西,我觉得很多同学还是一脸懵逼的,我还是不知道他为什么使用这样一个东西。

它存在的意义到底是什么,或者说它到底有什么样的一个价值,那这个时候我们来做一件事。

做些什么事情,光说这些理论的东西,光说这个图,我觉得你们都理解了好,但是我们要看一下源码里面,它到底是如何来进行实际操作的,我可以往这个地方放一些东西,什么东西,这定义好叫一级缓存,下面叫二级缓存。

再往下叫三级缓存,我定义三个缓存对象,后面可以往三个缓存里面放东西,放对象啊,我们来完整的模拟一下什么,当A杠B存在循环引用的时候,它是如何往当前这些缓存对象里面设置,具体指导。

我们把整个流程来进行一个优化,可以吗,可以吧,我现在你把这个流程过一下,因为我不带你们这个这块东西啊,我还是希望能够带你们debug的源码,因为如果不接吧,呃不debug源码的话。

这东西会显得非常非常麻烦,单说理论没意义,所以我们还是按照这样一个流程来,但是有的同学可能会说,老师我之前自己从来没有debug源码,我deb源码的时候,我应该怎么debug,或者你debug太快的话。

我跟不上怎么办,注意我让你跟上,所以在讲这些东西之前,我需要让同学们能够记住几个异常重要的方法,原文里面的代码和步骤是非常非常多的,我也不会把每一行代码都给你行,详细进行一个讲解。

这都不是最主要和最关键的,所以我们只说非常重要和核心的方法,到底有哪些,我希望你能给我记住六个方法,记六个方法能记住吗,同学们记这个方法能记住吧,我这应该没问题,好吧,我先写一下,你好好记一下。

第一个叫get be,他后面第二个叫do get be,它后面叫做create be,看后面,叫做do create,并再往下走,叫create bean instance,然后下面再来一个。

Populate be,一共就这六个方法,我觉得这个方法大家不可能记不住,也不应该记不住,也就是说你在看原版的时候,只需要留心这几个环节就可以了,别的东西我们都可以跳过,这没问题吧,就这东西。

然后我还需要再给大家提个醒,在原版过程中,在debug,过程中会出现套娃操作,所以每一个步骤必须明确到底,在干什么事,没问题吧,原版里面有很多套娃操作,或者有很多递归的操作。

很多同学其实蒙就蒙在递归上面了,你发现刚调完一个方法诶,又重新调用了,诶,又重新调用了,很麻烦,所以我把这些提前东西我都给你预先准备好,没问题吧,我们先来走这样的一个流程,当我走完这些流程之后。

我们再来解决这一块,这个map里面存在的问题。

就是源码里面,它到底为什么要使用三级缓存,来解决循环依赖问题。

好吧。

系列 5:P52:52、a到b循环到缓存优化源码讲解 - 马士兵学堂 - BV1E34y1w773

来啊看好了,我这定义了一个A对象,我把这个name都干掉,不要name了,可以吧,大家看到了,在A对象里面有一个B属性,没毛病吧,有set方法,有get方法,然后这我定义了一个B对象。

B对象里面同样有一个A属性,这把它干掉,不要它,这没问题吧,也就是说A现在里面有B了,B现在里面有A了,是不是这个过程,这是我基本定义的两个基本对象,当我定义好之后,我这用的是配置文件的方式。

因为我觉得配置文件的方式它更加好理解一点,所以打开我们配置文件,你可以看一下这个过程怎么做的,现在我定义了一个B对象,它是A的,然后看呃SQLA里面有一个属性,一个BREFB,还有一个B对象。

也是B对象,引用了refer a,Refer a,你告诉我这样的代码在进行debug过程中,它到底是否会出现循环依赖问题,知识代码会出现循环依赖问题吗,哎会不会啊,肯定会的吧,如果不会的话。

我们一会来测试一下好吧,来点个菜test,我这直接运行run啊,错了不行,用这个啊,上面这找到我们的circular test,来这个get name表,右击我先run一下吧,先跑一下。

大家先看一下这个问题好吧,我错了,我这每次都要编译源码,所以这个过程是比较慢的,你们如果不是编译源码的话,这个过程不会这么慢,直接引用炸包的话是非常快的,来看看这个过程。

很多刚刚说是会出现这样的问题的对吧,我们运行完之后,你发现了B对象我也打印出来了,A对象我也打印出来了,它并没有出现循环依赖问题,而为什么又出现,原因点在于我们spring中内置的三级缓存。

它帮我们解决这个问题,所以下一步我要看一下它到底是如何解决的,到底如何解决的,所以我们从debug开始看,我说过了,在debug的时候,这个过程是比较麻烦的,但是我直接带你们找到创建对象。

是从哪一个步骤开始的,好吧,还记得昨天我讲课的时候,我说了一个非常重要的方法,还有人记得叫什么名字吗,我说了一个非常非常重要的方法,还有人记得叫什么名字吗,Flash,这叫flash吗。

REFLESH吧,REFLESH好吧,Reflesh,所以这进来进来之后,先点F7跳过,这是一个static,是一个防止这个呃,WEBLOGIC8。1版本之后的一个小bug的东西,超过它,不管它是什么。

好吧,再点F7进来,尽量做到方法里面再点MC进来,这有一个REFLESH方法,我们进去进去之后,这里面包含了13个非常重要的步骤,这些步骤你都可以跳过,但是到这行的时候,我希望你能停一下。

叫finish be factory initialization,你翻译一下这句话,它上面的解释是什么意思,叫什么,这是什么意思,实例化吧,实例化所有剩下的非懒加载的单例对象。

就说在这个步骤里面我才开始进行实例化操作,所以我直接跳过这个步骤里面,别的东西都跳过来,点超过啊,直到变行到变量之后,为了验证一下。

我们可以打开当前的bean factory来看一眼in factory,找到我们刚刚说的一级缓存,二级缓存和三级缓存,来找一下那个叫什么来着,一级缓存叫singleton object吧。

你可以找一下啊,看着,在这个一级缓存里面,它有AB对象吗,现在有没有AB对象,一级缓存里面没有吧,没有,再往下看,这是二级缓存,有东西吗,没有这三级缓存有东西吗,也没有,所以从这个步骤开始。

我们才开始正儿八经进行实例化的关键步骤,从这开始,我们点FC进去,进去之后,上面都是一些对象属性值的设置工作,你可以直接跳过,不管它好吧,再往下进行,进到对面,从这开始,重要点来了,我问一下。

在当前整个应用程序里面,我需要创建几个对象,几个告诉我两个吧,就俩一个A1个B,所以我刚开始我先获取一个东西,叫this点bedefinition names,昨天我带你看过这个属性了。

除了这个属性之外,还有个叫什么叫病戴芬尼森MATT吧,里面放的就是我们要创建的bean,对象的一些BD信息,那这里面肯定有两个吧,所以你打开这个NES之后往下走走一步,你会看到当前这个集合里面有两个值。

一个A1个BA和B谁先创建谁后创建,无所谓好吧,爱谁先谁先爱谁厚谁厚,没关系的,在下面我要开始循环取了,刚刚例子里面看到了是AB开头的,所以一定是先创建A对象吧,是不是一定要先看对象。

所以从这开始完之后,第一个我获取到的病名称是A,比如说从这个步骤开始,我要创建A对象了啊,中间有一系列的判断步骤,第一步获取一下我们的bean definition,好吧,中间有一系列的判断。

我们都管不管它,但最终我需要找到一个东西,啥玩意儿,这个方法,能看到吗,这放干嘛的,我刚刚有没有在你说这个有没有说这个东西啊。

它叫做get be,还记得第一个方法吗。

是不是get in,你告诉我这get in是干嘛的,注意了,当你在创建对象的时候,我每次都要去我们当前的容器里面,判断一下我之前到底有没有创建过对象,所以我会先获取一下B根据A去创建并对象,那很明显。

你告诉我我之前有创建过吗,没有吧,所以紧跟着听到一个方法叫do get in,这是我说的第二个方法,Do get in,再点FC进去,进来之后转换一下名称,不管它来往,这看叫get singleton。

你通过名字方法你能猜到什么叫get singleton,叫获取单例对象吧,那很明显我刚刚说过了,我说现在有A的单例对象吗,有A的单对象吗,没有有啊,1800821有吗。

你程序运行到现在有创建对象这个环节吗,没有没有,所以这个值取出来之后,它一定是等于空的,等于none,等于NN了,怎么办,我是不是该去创建对象了对吧,我该创建对象了,因为没有对象,我肯定要创建嘛。

你不创建,你后面怎么用呢,所以往下走,下面有一堆的条件判断,我们直接跳过,不看这些步骤了好吧,唯一拿走走到一个步骤里面,走到这一行,说MBDESLETON,说,我们当前的A对象是否是一个单例的。

默认单例吗,我没做任何配置,默认就是单例的,进来之后叫get singleton,好了,你看到了第一个方法叫get singleton。

这个get singleton跟上面这个get singleton,它方法名字是一样的,但是传递的参数不一样,第一个里面只需要传一个冰name就可以了,而第二个里面我除了传一个冰name之外。

我还传了一个什么玩意儿,看这段代码是什么鬼。

是不是相当于我传了一个拉姆的表达式,把它拿出来,站出来,我把中间那些注释都干掉,不要浪费空间干掉,是不是这样东西,这里面其实就指向了一个东西,叫create be CD变吧,就调用这个方法。

我问一下,当我们在进行具体调用的时候,现在我一进到或者我一调用get sn方法的时候,这里面的东西会被调用执行吗,就这个la表达式它会被调用和执行吗,会不会,不会吧,不会调用执行的,我说过了。

他什么时候掉,在执行get object方法的时候才会掉,所以它只是当成一个参数,传递到了get singleton这个方法里面去,所以我点FC进去,进来之后,第一个断言,第二个加锁,不管它往下走。

往下走来往下走走走走,一堆的判断逻辑好吧,当我走完之后,走到下面这行,你看这块了吗,叫singleton factory,什么叫singleton factory呀,往上翻。

singleton factory指的是啥,你告诉我这个singleton factory指的是什么,啥东西,lambda表达式吧,前面拉姆表达式对不对,也告诉你类型是什么。

是object factory类型,所以当我这个地方我在调用get object的时候,你告诉我我实际执行的是什么方法,是一个什么叫做create bean吧。

所以点F7我进去到create ban了吧,所以这是我给你们说的第三个方法叫create bean,再点F7进去,记住这上面一堆的赋值和其他操作,不管它好,不再往下走走走,走到这一行,你看到了什么。

方法名称叫do create定吧,是不do create变明白意思吗,这是我需要给大家提个醒,同学们注意了,在整个源码过程中,研发过程中有很多方法名称前面是带着do的,当你看到do开头的方法的时候。

我希望你能够给自己提个醒儿,为什么,因为带do的方法才是实际干活的方法,明白吗,就说我们实际真正的处理逻辑,数理逻辑都是在do开发方案里面执行的,你想一件事,这涉及到杜奎的病呢,你下一步是干嘛了。

我是不是该真的去创建对象了,对不对,真出对象好吧,所以我再点F7进到这个逻辑处理里面去,点FC进来,进来之后,这有一个ban Viper,昨天你说过这Viper是一个包装类,无所谓好吧。

你可以把这个ban Viper直接等同于我们的对象,往下走,往下走,往下走,到这个步骤是啥玩意来着,还记得不叫create bean instance,什么东西。

我跟你说第五第五个方法吧,叫create bean instance,你少一个S,是不是东西他要干嘛的。

这不是干嘛的,它是用来进行具体的实例化操作的,我带你们看一遍好吧,里面干什么事,其实我问一下,我们都知道对象里面的呃,容器里面的对象,都是通过反射的方式来进行操作的。

我问一下反射代码,大家还记得吗,我们写一下好吧,第一步骤获取class大写C,获取class对象吧,啥玩意,第一步是不是有对象,当我获取对象,第二步在干嘛,是不是叫construct c t o r。

等于class点,Get declare the construction,什么意思,是不是要获根据我们当前的卡class对象,来获取到我具体的构造器了,当我获取到构造器之后,第三个步骤在干嘛。

是不是叫object o b j等于CTOR点new instance吧,我是不是通过这个步骤能创建出来,我们具体对象,这没问题吗,这个问题没,这个视频是录播吗,是的,这个反射我觉得应该会啊。

我觉得过分了,说明你的基础真的掌握的有问题,所以这个机器人的反射东西你要了解,所以我们在看那个critical instance的时候。

我也要去找到具体的逻逻实现逻辑怎么找,点F7进去,当然里面啊依然有一堆东西很多好吧,我们只看到往下走走走走走,跳过跳过跳过一堆好吧,跳过不看它,不看它走走走在外走。

走到这行叫instance bedmc,进去进来之后往下走,到我们的实例化环节好吧,往下走走走走走走走,来看这行代码告诉我什么意思,看这行代码什么意思。

class点get declared constructor,不就是获取到我们对应的构造器吗,当我有了构造器之后,我是不是该用构造器来创建创建对象了,往下走走走,走到这一行,再点FC进去。

进来之后上面一堆判断跳过去,不管它不管它,不管它,到最后一步叫CTOR点new instance,你告诉我,我是不是通过反射的方式来创建出具体对象了,是还是不是,没问题吧,所以这个步骤里面干什么事。

就是通过反射创建对象,就这么简单,没别的意思。

没别的意思好吧,就这块处理的逻辑,我来我们返回去啊,返回去返回去返回去返回去返回去返回去之后。

我们来看一下这个病对象,现在我的病对象已经有了,这是有个A是不是有对象叫a at1573吧。

我们这儿记录一下,记住对象叫a at1573,我的问题是同学们现在B属性有值吗,B水有没有值,没有吧,B等于公记录下来对吧,现在我这玩意儿,我有往任何的1233个缓存里面放东西吗,我没往缓存里放啊。

我只是做了一个记录,表示说他是A对象了,但是我还没往我们的三级缓存里面扔东西呢。

一点都没扔,所以接着往下走,往下走好吧,抑制买家进行相关的一个处理吧,按道理说我第一步对象有了,下一步该进行实例化了,但是恰巧不巧的是什么,在整个实例化环节的时候,这里面有这样的一个判断逻辑。

有这样一行代码,这行代码其实就是三级缓存最主要的点,因为你往上看,这儿有个东西好,Early catch singletons to be able resolve cooler reference。

说这个东西能够解决我们的循环依赖问题,这源码里面写的注释,就这行代码它会变得很重要,来看这行代码,第一个参数是b name,问一下现在的b name是谁,A吧B是A没有B的事,还没到B呢,好吧。

就是A就是A后面这又是个啥东西啊,啥东西又一个lb表示好了。

我把这浪表达式拿出来,所以这里面啊拉达是比较多,它有它非常重要的核心作用,我把它写了下来。

我要放这块儿啊,做一个标记,这张表示,所以同学们想一下,当我开始执行的时候,它会直接掉档表示吗,不会我们看一下这个adsingleton factory干什么事好吧,点F7进去下来之后往下走走走来。

第一个步骤干什么事,第一个步骤,干什么事,告诉我,叫this singleton factories,点put b name,加singleton factory,把谁放到三级缓存了。

来key等于什么,等于A吧,value等于什么东西,value是A对象吗,不是啊,value放的是谁,放的是拉姆的表达式,value放的是拉姆达表达式,它不是半成品,也不是成品。

不管是我们的成品还是半成品,没往三级缓存里放吧。

我三级缓存里面放了什么东西,C功能factory sfc是谁,这个参数参数是谁,拉表达式是不是这个意思,所以这我只需要放拉表达是不是可以了。

没问题吧,来这个步骤没问题的,扣一,一定要跟上好吧,这些核心步骤一定要跟上。

这放到三级缓存区,放到三级缓存之后好了,往下走叫early signal remove,把二级缓存给移除掉,二级缓存本来没东西嘛,也不需要移除好吧,再往下走叫register singletons。

我们这没关系,它不属于三级缓存,所以跳过去不管好了,也就是说刚刚这个步骤里面就干了一件事,把我们的拉姆达式扔到三级缓存里面去了,当我扔完之后,同学们,你告诉我紧跟着下一个步骤该干嘛了。

我A对象是不是已经创建好了,挺好,A对象就创建好了,只不过它是一个半成品的对象,所以下一步我需要给A对象里面的B属性,来赋值了,那复制的方法叫什么叫populate bean吧。

这就是我们跟你说的第六个方法叫populate be,我现在已经在里面把这六个方法都过了一遍了,之后,你还会看到这六个方法的这个流程,我希望你能把这个方法给我记住。

所以这个步骤干嘛的,populate啥意思啊,什么叫populate填充嘛,叫属性填充啊,所以这里面我开始进行属性的赋值操作了,怎么复制啊,也很简单好吧,点F7进去进来之后。

上面一堆的逻辑判断跳过了好吧,不重要,不管它,你们不用管它干嘛的好吧,往下走,直到最后一行叫apply property values,叫应用属性值,比如说这个步骤才是最关键的属性赋值的步骤。

我只有走到这个步骤里面才会进行属性赋值,卡了吗,卡的同学刷新一下好不好,刷新一下好吧,自己刷新一下,我等一下卡的同学刷新一下,自己刷新一下,你们可能用的是浏览器看的,所以可能会卡一点。

如果你用客户端的话,他不会卡的,把自己刷新一下好了吗,你们刷的,我抽根烟,好了吗,好了好,现在往下讲到这个步骤的时候,它是很重要的步骤,叫apply property value,这叫应用属性值。

也就是说往属性里面进行一个,最基本的赋值操作,好吧,我们点F7进去,进来之后,我想问一下A对象里面有几个属性,一个吧,只有一个B,所以往下走走走,这些都跳过了啊,不带你拿一个看了没意义好吧。

我带你们看看关键步骤里面,去带你们找关键步骤好了,唉这行第一步叫PV点get value,PV叫什么叫property value,它封装了一个对象啊,就属性value值拼装了一个对象。

第一个叫获取名称,我们的名字叫什么叫B吧,叫B啊好吧,第二个叫获取value,获取一下我们B的value值,这时候当我获取完之后,我希望你把这个value值给我记下来,你看一下这个value是啥。

是啥叫wrong time being reference,啥玩意儿啊,什么叫wrong time being reference,这东西你可以不知道它是干嘛的,但是我希望你能先把这个词记下来。

我已经敲出来了,叫状态bean re,你把这个单词给我记住,因为后面我们会用到这个wrong time being reference,往下走,跳过在这一行叫resolve value。

if necessary说如果必要的话,我需要去处理当前值了,我们这个wrong time be reference,它不是B类型对象,所以我是一定要把这个值进行相关的一个,处理工作的,所以点F7进去。

当我进来之后,来同学们告诉我,我们的value是不是wrong time being reference,是还是不是,是吧,所以这时候不谋而合,正好匹配上了,既然我匹配上了。

我就一定能进到我的if判断里面去,所以先进行一个类型的强制转换,转换之后叫resolve reference,叫处理引用,我需要把这个long time bean reference。

转成我需要的B对象了,所以点F7进去,进来之后获取类型,判断有没有复工厂好吧,往里面进行一堆操作不重要,来往下看,这样处理的东西也要注意到name或选名称,名称是B没问题吧,来看这一行代码。

套娃从此开始叫this bean factory,点get be,这是你第几次见get电脑,同学们告诉我,第二次刚刚创建A对象的时候,我见过一次get变了,现在我又建了一次get变的方法。

是不是意思好吧,所以现在我见到两次了,这是干嘛的,我说了,每次我在创建对象的时候,我需要先从容器里面去获取,或者判断一下有没有B对象,我现在在B类模块是谁了,发完B了吧,是不是就相当于有干一件事。

我要判断一下容器里面到底是否有B对象,来到这为止,能听懂的扣一,问题吧,所以来我点进去点F7,进来进来之后你看到了什么,第二个方法叫do get be,我再点F7进去好吧,往下走,从容器里面获取。

我们带对象,有B对象吗,现在现在有没有B对象啊,有啊,宋祥坤没嘛,没创建的,怎么会有呢,没有没创建过,没有没有没有没有没有,所以这个对象依然是等于空的,一等于空没创建的,所以肯定没有。

你就严格按照我的标准步骤去走没有,那如果没有的话,你告诉我下一个步骤该干嘛了,下一步该干嘛了,创建B对象,所以往下走走,跟刚刚的流程一模一样,一模一样一模一样,所以走到这行叫get singleton。

我再点进去get singleton,进来之后往下走,往下走,往下走,往下走,往下走,往下走,往下走,找到我们的get object了,来问一下这个get不get,我要调谁了,我要到谁。

create bean方法吧,该调create bean方法了,所以点F7进去到create bean,再点F7进去到create bean方法之后,我要找谁了,是不是该找do create变了。

所以你发现了流程一模一样吧,你刚刚看别的流程,现在又是这面流程一模一样,所以原版为什么看起来比较难,你如果真的把一遍捋通了的话,它并不难,你懂了吗,那一点都不难,它很容易,所以往下走走走。

我们找多亏的病走do奎bean到这吧,终于到do cret bean了,然后当我到do cret bean之后,下一步在干嘛,点FC进去吗,进来之后往下走走走走,就到这一步了。

叫create bance,我这边不用不用带你们看了吧,它用来创建哪个对象,training对象,B对象,B对象,所以往下走完走完,我们来看一下当前B对象是谁,叫b at2171对吧。

我把对象留下来记一下,叫b at2171,现在A等于那没问题吧,我现在AB对象全部都有了,全部都有了,全部有了之后,我再接着往下走,往下走,下一步啊,走走走走,下一步走走走走走走走走,走到这一步。

你告诉我干嘛,这不也见过吧,这不是干啥的,往三级缓存里面放东西吧,放的是啥,来改了,待会呢,key冒号是b value冒号是谁,拉姆达表达式好吧,而我们这儿指的兰表达式,就是下面的拉姆表达式。

是放进去好了,放完之后结束了,回过头来我再接着往下执,行到populate bean,一模一样的逻辑,同学们还是找populate bean点FC进去好吧,来走走走,跳到最后一行,跳过啊,跳过最后一行。

走到第一行叫apply property value,再点进去,这时候问题来了,我的B对象里面有几个属性,第一个吧只有一个A属性,只有一个A属性,所以往下走,我依然跳过这些无关紧要的步骤,好吧。

不管他走走走走走走走走走,来到这,第一个,我先获取属性名称名称是A,第二个我在获取属性的Y6值,来看一下当前的value值是谁,又是wrong time being reference吧。

不是两个表达式啊,是wrong time being reference,叫run time bean reference,运行时对象引用好,运行是一个B类引用,所以它是没有任何的一个变化。

叫状态并reference还能搞清楚那一样的,我问一下,我们刚刚看到创建B的过程,跟创建A的过程一样不一样,一样啊,所以我说什么叫流水线工作,他就是这样一个标准流程,它没有任何区别,就这样一个流程。

所以我们接着按这个流程往下走就可以了,好吧,往下跳一步到resolve并resolve value,if necessary点FC进去。

value是不是wrong time being reference是吧,value是不是也是这个类型类型,如果匹配的话,我进来进来之后,我要处理的引用了,要result reference。

我再点F7进去,又回到这块往下走,往下走,往下走,获取到我们的属性值等于A,这是你第几次见到get变了,同学们第几次,第三次,那你告诉我,我现在的get bean是要get谁,是不是该get a了。

get a了一样,我再进去点F7,进来又回到这了,Do get in,我再点F7进去,是不是又来第三遍了,同学们,他是不是套娃,是吗,为什么好多同学理不清楚,就算这玩意一遍一遍重复在那重复。

在那从那重重复滚滚,一会儿同学们就懵了,所以别蒙我,就到目前为止,你们应该还能跟得上对吧,来能跟上同学扣波一,没问题吧,跟着我的节奏好吧,跟着我的思路去往下捋,往下捋啊,慢慢来,走完之后往下走。

往下走来,现在我的问题来了,这个时候我能不能获取到A对象,这个是什么,能很多同学都告诉我,能,如果能的话,那我们是不是要看一下这个get singleton,里面的处理逻辑了。

我们看一下到底怎么过去的好,有人说不能不管能不能,我们判断下逻辑好吧,总总没问题吧,我看一下到底怎么操作都没问题吧,我点F7进去,再点F7进去。

来看一下这一长串代码,很多套代码之后我蒙了,别蒙,我们挨个来捋,第一个,这是几级缓存,这几级缓存,三级你确定是三级吗,来姐姐,signal vs1级嘛,先从一级里面取,我问一下,按我们这个图里面画的。

一级里面有东西吗,一级里面有东西吗,没有,所以这个值很明显,我取到一定等于空,signal object等于空,第二步这个判断就很重要了,说singleton object如果等于空。

并且叫is singleton currently increation,什么意思,说你当前对象是否在被创建过程中,我问一下,我们的A和B现在是否都在创建过程中。

是吗是吧,所以就等于true吗,所以这种条件能进来,进来之后我再从哪取,这是几级缓存,二级吧,我再从二级里面取那一样的,二级本身就等于空嘛,它一定也取不到,如果取不到的话,我再往下走。

这有一个双重的一个星空,net的一个检查,检查的时候里面一样,先从一级里面取,取不到,再从二级里面取,二级里面取不到,再往这来叫this singleton factories,点get,我问一下。

现在我是从哪儿取,到三级了吧,到三级缓存区了,我从三级缓存取的话,我的问题就来了,同学们,我这个时候取出来的是某一个对象吗,挺有问题啊,我取出来是某个对象吗,不是我取出来是什么。

是一个拉姆达表达式,所以当我取出来lb表示之后,我需要通过什么方法来执行,Get object,是叫这get不JECT,当我这在调用get object方法的时候,我实际执行的方法是哪个。

是不是这玩意儿叫get early being reference吧。

所以来我们点进去点F7进去,你发现了,我跳到了get early bean reference,对不对。

跳到这块了,我再点F7进去好了,到这一段的处理逻辑了,这一段处理逻辑才是三级缓存,它的精髓所在,这个方法这个逻辑精髓,来我们分析一下第一个步骤,并对象,我把当前的并对象是A8AI1573。

我赋值给了叫exposed object,什么叫exposed object呀,怎么翻译,怎么办呀,叫对外暴露吗,这就是叫提前对外暴露对象,暴露对象暴露谁暴露,是这里面的exposed obje好吧。

然后中间这样一个一分判断,既然是一个if判断的话,就会收到一个问题,这个if可能进去,也可能不进去,但是你返回值是什么东西,是不是一次不做,这对吧,我刚刚如果我的衣服进不去的话。

我返回什么东西告诉我听好啊,如果我的if进不去,我返回是谁,返回什么原始的A对象吧,原始对象如果我的if判断我能进去了,这个地方是不是会改变我们的expose object,是不是改变怎么改的。

我们先不管,但不管怎么样,我这个步骤到目前为止往下走,跳过是不是直接返回了A,所以往下走往下走,现在我取到A对象了吗,同学你好,我现在有没有取到AB项,提到了吧,学到了吧,A是A。

A是a at1573吗,还是对象取到了,取到之后干什么事,看这个步骤,什么东西往哪放,是不是该放到我们的二级缓存里面去了,所以当这个步骤完了之后,我要往二级缓存里面移动了。

这变成K冒号还是A但是value冒号变成谁了,叫a at1573,但是现在的1573它是一个什么状态的,什么状态的成品,还是半成品,成品半成品,半成品是半成品。

因为现在你这个signal里面B还是等于空嘛,所以还是半成品无所谓,好吧,往下走,叫this singleton factories remove,干嘛,我是要把三级缓存给移除掉了,把三级缓存给移除掉。

我们这不真的删,我把它标记为一个其他颜色,比如说这个色这个色儿表示删除,我们不算三啊,我把这个表就是这个色调表示删除。

可以吧,好了,现在我也取到我们的A对象了,回过头来回头来回到这块,当我取到我的A对象之后,你告诉我,我还需要接着去创建A对象吗,需要吗,不用了吧,所以你在往下走的过程中走走,直接返回B对象了,是不是。

这个时候我把A对象取消了,对不对,A对方取到了,我问一下啊,我问一下,现在我取到了A对象,我刚刚为什么要取A对象来着,我刚刚为什么要取A对象,还记得吗,所以往下走往下走,往下走往下走。

再返回一直返回返回返回返回返回往下走啊,处理完处理完,处理完处理完处理,处理完拿走到这一步叫BW点,set property value给谁设置,给B设置,所以当这个步骤我走完之后。

现在我的B对象它是一个成品还是半成品,聪明吗,A已经复制完了吗,所以你点开之后,你发现A对象已经有值了,但是A里面的B现在有值吗,A里面的B现在有值吗,没有吧好吧没有,不管它接着往下走。

后面是初始化环节,可以直接跳过,不重要好吧,往下走往下走,往下走,走完走完走完走完走完走完一直往回返好吧,这是刚刚创建B对线的过程,当我这块完了之后,来到这个方法里面,这还有一个方法很重要,这干嘛的。

叫ADD singleton吧,你点MC进去进去之后往下看叫singleton object,点put signal object,是几级缓存缓存,一级吧,b name等于B吧,SNL不是等于谁。

b at2171吧,所以现在我把我们的一级缓存里放是谁了,K冒号等于b value,冒号等于b at2171,它是一个什么状态的对象,商品对吧,成品对象好吧,成品对象整理完了之后往下看。

叫this singleton factory remove,这是直接缓存,这是几级缓存三级吧。

所以我把三级我再给它清空掉,移除掉对吧,然后回过头来再往下走,我再把二级给移除掉,二级里面本来也没东西移除掉就可以。

就就就就移除掉了,无所谓,OC走完走完走完走完走完之后,往回返回返返反反,现在是反反到这个步骤之后,刚刚是不是去创建B对象去了,我问一下为什么要创建B对象来着。

为什么要创建B对象来着,是为了给A对象里面的B属性来赋值。

所以我去创建B对象了,所以现在我已经获取到我们的B对象了,那我剩下步骤干嘛,我是不是就该给A属性赋值了吧,再往上走走走走走走走,走,完到这个步骤叫BW点,Set property value。

设置完成之后拿走这步骤,我问一下A对象里面是A吧,A现在里面是成品还是半成品,A成品了吧,是不是这个过程了,所以现在A是不是也成了一个成品对象了,成品完了之后往下走走走,返回好吧,人往下走。

走完走完走完走完走完走完走完,走完之后到最下面到这块叫ADSINGLETON。

也是往一级缓存里放吧,所以这我再往一级缓存里放对象,这是K冒号,a value value冒号,这写一个a at1573,现在什么状态。

通过对象吧,完了之后把三级缓存移除掉。

把二级缓存移除掉,把它移除掉对吧。

当我移除完成之后好了,整个过程我就结束了对吧,A对象创建完成了,当A对象结束完成之后,回过头来,这时候该干嘛了,同学们,刚刚别忘了我们有ab两个对象,我刚刚是为了创建A对象的时候。

我把B对象给创建出来了,但是实际情况下我B要不要创建了,必要不要创建了,要吧,所以我接着取第二对象等于B,只不过B在进行创建的时候get get,这能获取到我们的B对象吗,能获取到能吗。

因为一级缓存面积有了吗,还不能啊,大叔能吧,因为我已经放到一级缓存里面去了,所以肯定能,所以当这步执行完成之后好了,我的B对象取到了,取到之后,我还有必要create吗,我是不是直接返回就可以了。

这个时候我的ab就结束了,这是我们刚刚ab已经结束这个流程。

所以刚刚我带你们debug过了一下这个流程,你现在还觉得模糊吗,有没有捋清楚一点,对吧,这个时候牛逼是不是应该刷刷起来了,明白意思吗,你们为什么一直模糊,原因点就在于什么,你们从来没有像我一样。

跟着把这套流程给刷一下,梳理一下,如果你真的梳理清楚之后,它还难吗,你把每一个对象都放到这里面去,挨个步骤去迭代,它还难吗,它不难啊,最起码没你们想象中那么难,所以我一直给大家说,我说你注意了。

你一定要注意一件事,什么事注意思路和方法,这事比什么都重要。

懂了吗。

posted @   绝不原创的飞龙  阅读(50)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
· spring官宣接入deepseek,真的太香了~
历史上的今天:
2020-11-22 李宏毅强化学习完整笔记!开源项目《LeeDeepRL-Notes》发布
点击右上角即可分享
微信分享提示