00:00
下边呢,我们来说一下这个local,用这个local来解决。的问题,就是说我们现在呢,我们写的这个代码。在base DAO里面被do里面,这里边的话呢,每个方法怎么样,是不是获取了一个单独的一个链接啊,这个时候是没有办法完成事务操作的,大家想先不想我们刚才说那个select local啊,那目前以我们的这个技术的话,我们能不能实现这个事务呢?我们这个事物方法是不是就这一个方法是要求事物的呀,别的都是单个操作吧,都不需要我们能不能完,我们能不能在这个基础上。就是说以现有的这个技术来完成这个事务操作呢,能不能呢,能不能。也可以吧,前提就是在我调这个方法的时候,我把这个connection传进去吧,然后整个每一个方法都需要传入connection。
01:04
每一个do方法传入connection,然后在上面开事物,然后写个TRY开提交事物或回滚事物是不是就可以啊?但那样写的话呢,我们这个service将知道底层DAO用的是具体的是什么技术,比方说是JDBC或者是harm。这样写不好,而且代码也特别冗余。我们也不希望这样,就是你每一次在service里边你都得写类似的这种代码,我写大家看一下啊,大致是这样的。呃,Do,然后呢,需传入nineteen。对象,当然了,这之前我先获取一下。
02:02
然后呢,开启事物。然后完了之后呢,提交。黑肠。回国之后,然后呢。关闭链接。每一个都需要这样来写。啊,整个,然后这个代码的话呢,放在这个里边就是什么,就是用一个样板一样,每个都这么写很麻烦。所以说的话呢,我们不要这么写,那我们怎么办呢?还有我们希望啊,我们希望。
03:01
不这么写。我们希望。就在这个基础上,他能够完成这多个。DAO就是一个DAO方法。两个DA方法,三个DA方法,四个DA方法用一个connection。这个事看起来很神奇哈,为什么呀,我是不是没往里边,没往里边传可难吃呢,我没传,然后的话呢,我还要求这些个dau方法,这些DA方法里边的话用的是一个connection,换句话说这里边哎,我这个connection这么获取肯定不行啊,这个connection我从哪块拿过来,然后用的是一个connection。而且还不会有现成安全的问题。怎么搞这个呢?就需要借助于我们这个stress local和我们下边这个filter,那我们首先呢,就对这个local,我们来进行一个简单的测试,简单的我们先来看一下这个local是什么。
04:07
兰多口。好了,我首先呢啊,我让他是一个re。实行状机构接口,比如说它是个什么呀,是状构对象,然后呢,哎,我来写上一个字针。Name等于no。这个方法。这个它I等于零。负循环。I小于10A加加。然后呢,我首先我为内个值,为什么呢,为当前现的。付完了,付完之后我打一下,我打成什么呢?我打上当前线程的名字。
05:04
加加上谁呀。Ju name。保存。还上去吧,那我如果中间我让县城睡这么一小会儿。十。好了,这是我的一个这个线程安全的一个模型解密方法。TLT等于new,然后new。RA。嗯。他给的是谁呀?名字AA点。但一个两个。这个bbb,好了,我们先跑一下,看看结果是啥样的。
06:06
大家看是不是出现了这个线程安全的问题啊,能想明白是咋回事吧?我第一个线程的名字是不是叫AAA呀,这名叫bbb吧,看着安全打出来呀,我这两个线程是不是操作同一个name啊是吧,那我于是的话呢,我第一个线程为这个name赋值了,然后我是不是断了一下呀,那我在打印的时候,那我我在打印的时候,我这个名,我这个线程的这个名就应该是就应该是另外一个线程的名了吧,所以说会打出什么呢?会打出这个来。叫BBBAA,那我如果把这个去掉。我要是呃,不多次做的话,就很难发现这个线程安全的问题,那实际上它是有这个问题的是吧,你要打多了的话呢,是有的是可能会有的,比方说你这个你写成什么大一点或许能看到啊。
07:05
也顶着。或许。因为我这个是什么四核的是吧,嗯,没看着。我们就不再一个一个做这个实验了哈,或许能看到,那我们解决这个性能安全的问题最好的方法什么办法?什么办法,我把整个这个括起来是吧,使用什么?使用single吧,Single我写个days,把这个拿进来。大家看。这个时候就没有线程安全的问题。啊,非常知道我们看到了啊a ABB都有。哎,没毛病,好了,把这个去掉。往前。串你看这个时候就有线程安全的问题,就我们刚才已经看到了ABB好了,这是我们前边呢讲的关于这个呃,线程的问题,那现在呢,这个内幕啊,会有现车安全的问题,那我现在我改为所在的logo,我们看一下。
08:15
这个。这样吧。这个上学写的二。看这看这这个呢,我把这个改掉,改成。Slide。正ad local等于new thread local写完然后呢,这个值啊,那不正写完这么写,我往里边放一个值。Set放一个什么呢?放一个current the name放好了好了,我打的时候呢,我还这么打,只不过这怎么了,我从这里方把这个值取出来,Surprise local.get看见了吧,就是我这个select logo啊叫线程本地的,我把这个名字放里边,然后同样哎这块的话呢,我也有这样的一个效果啊,然后这块的话把这个值取出来,我们看这个这个时候会不会有这个安全的问题呢?没有。
09:32
哎,有哇,打跑他应该对吧,跑错了。你看没有。无论怎么跑的话,肯定都没有好了,这个时候我们就看见啊,这个时候实际上就没有我们刚才看到的这个问题,那我们要深入的看一下,它是怎么搞的呢?他为什么不会有这个问题呢?我们看那个set方法。看着特源码哈死兰多和源马赛。
10:01
大家看我把这个值啊,放到了一个map里边,其中这个键是谁呢?这个键是这个local对象是this吧,值就是这个值,这个map是谁?这个map是。RI调这个get map方法吧,点一下看这个map是谁呢?这个map是在我这个呃RI logo里面,这个T看见了吧?这个TT是谁呀?Thread thread里边有这么一个map,线程里边有这么一个map叫thread local map这个呃,变量名呢,叫thread local。好了,我们给他。再归结一下啊,咋回事呢?这个意思,我在放这个变量的时候啊,我把我把这个变量放到了一个map里面,那个map是谁呢?那个map是线程的一个,线程类的一个什么呀?线程类的一个叫thread local map这么一个类型,然后呢,这个键是谁呢?这个键是thread local本身看着放的,你看我把这个放到map里边了,这个map是谁呀?这个map是从这个里边来获取的,然后这个键是这个RI local本身好我这么放的,看怎么取呢?Get。
11:35
取的这个取呢,同样我是从map里边给它取出来,以以什么为,以什么时候为建的,以当前的logo作为这个键给它取出来,看一个图。我有好几个线程,线程一,线程二,线程三,然后呢,哎,我有这么一个变量,我这个变量啊,实际上是放在这,放在了这个map里面,这个是什么,这个值就放在这个map,如这个键是谁呀?这个键是这个stress local,那你这个时候的话,我要是把这个值都这样放我这个,我这个值放到了我这个现成的一个map里边,以它作为键,大家注意看这它是什么呀,这个是键吧,这是一个键好了,而我把这个值放哪呢?我把这个值放在了我这个线程的每一个线程,对于一个每一个线程对象,它们都有一个local这样的一个属性,是这个意思吧,那你想你想我放到这个map里边的话呢,这个是键,这个是值那。
12:52
那我我的这个变量是实际上是不是就是跟我这个线程绑定了呀,那我这么运行过来之后的话呢,我再用这个后再取出来,它当然是毫发无损了,就这么一回事,回来看这说通过呃,Set方法将对象的引用存到线程各自的一个map里面。
13:21
就是线程本身都有一个map,每一个线程都有这样的一个map步,执行这个get的方法的时候呢,各线程从自己的脉方法里边取出来,因此取出的是自个儿那个线线程里边的对象,值得注意的是啊,S select logo对象各为那个key出现的。然后说,一般情况下,通过select set方法到全程的对象是该线程自己使用的对象,其他线程不需要访问,因为我把那个变量放到了。当前线程的一个map里面。好了,再说一遍,啥意思,右键。
14:03
清除。好了啥意思呢,就是说我每一个线程里边啊,都有这么一个重新变量。诶,当我调用这个th local的set方法的时候,我把这个变量值本身放到了我每个线程的map里面,但是我是以这个作为键好了,这样我这么线程一跑的话,我任何时候我是不是在我自个儿这个map里边把这个值再取出来啊,那当然其他线程取不到,它也不会发生这个,嗯,说说这个变量跟这个变量有什么混淆的问题,他不会这样。但是呢,这个这个我们需要说一下啊,这个应用的场合是呃,多线程实例的。每一个线程实例都有一个对象访问,我们是用这种情况下,就是说多个线程,多个线程实例我都需要和一个对象绑定的时候,这个时候用,而这个它不是解决线程安全的一个本质问题,就是说如果这个set方法放进去的这个,呃对象本身它存在着性能安全问题,我们这个是无法解决的,它还是会出现性能安全的问题,但是我们这个代码我看一下这个。
15:32
看这个回到我们这个text里边来,你看啊,这个这个我这时候我放的是谁啊,我这个时候我放的是不是这个name值,我如果给他改一下,这么改好了,如果你把这个值这么。CRLXCV,然后呢,你放的是什么呢?那它还是会容易出现线程安全的问题,你先看。
16:10
这个我看一下啊。我把这个name值放进去了,然后的话呢,我在取的时候。我把这个值又给它取出来了,我们看一下。嗯。Name等于他啊,那你要这么写的话,不会我这块的话呢,你就这么写,我要是我要这么写,跟刚才这个写法是不是一样的。好了,那我这个写法的话呢,我们看一下,嗯,说我如果我thad local放了这个对象,同样是一个,呃,线程安全容易出问题的一个对象的话,它也会出现线程安全的问题,看我这个应该不标演示啊。The local name。
17:01
这是钢铁进程的名字,放进去。然后呢,我们希望一个时刻呢,把这个职能改掉,把这个往上穿一下。啊,这边再放一个就可以了。The proceeds enjoy。嗯。我发音不对啊。对,缓一下。大家看是不是依旧会有线程安全的问题,它一定会有,它不是解决线程安全的问题的办法,但是它可以把一个变量和这个线程进行绑定,你要这么写来过来看,我还这么写看,虽然说我目前有两块啊,但我只要我放的这个只是它就不会有。
18:02
C这个时候为什么不会玩,把这个去掉,它为什么不会玩,因为我每次我都把这个值放进去了,我取的还是这个值,本身这个时候就不会,确实不会,那刚才这种情况,它为它为什么会啊,大家看我取了一个值吧,然后完了我停下来了,我这个值的话呢,有可能是AAA啊,这个值是AAA,好,我停下来了,我停的话的话呢,我是不是要往里边放啊,这个时候放的话怎么了,放的话有可能是另外一个线程了吧,懂吧,就是bbb那个线程,我把这个AA那个值放到bbb里边了,那它不还是有线程安全的问题,所以说我们这个stresslo啊,它不是解决线程安全问题的方案。但是的话呢,它能够适用的场合是啊,多线程对于对象的访问,它可以很好的进行解决,那于是呢,我们结合。
19:03
结合什么呢?结合filter就可以完成一个很好的操作,我写一个transce filter叫什么呀?叫事物的filter,我在把这个请求到这个service之前,我把这个connection啊,跟当前线程绑定,就用这个local,然后到service,到service到DAO里边怎么了,我再给他。取出来。好了,我这块放的这块曲,我这么一个过程是不是一个线程啊,我一个请求是一个线程嘛,所以说这个时候的话呢,我在这块放的这个connection,我在这个DAO里边就可以取出来,那当我这个service去调多个DAO的时候,你取的是不是同一个connection,所以说这个问题就解决了,那后来写一下。过来看,我需要写一个filter。
20:02
Filter。买三星。下一步过滤所有。好了,我们直接看这个就可以。好,这块的话呢,我来写这个。我们看我们说啊,在我调这个do filter之前,干这样几个事,第一个获取链接,第二个把链接和当前线程,当前线程绑定,那这个时候利用自然local了啊,利用slide local好三。
21:04
把请求,把请求转给目标,都往后转吧,四不出异常呢,提交事物,当然最后还有一个,这是二开启事物。开启,然后的话绑定。然后是调用提交非常呢,哎回本数六回滚十七七什么呀,关闭链接。
22:01
来看这个事儿,这多好,谢谢。八、第一个action放外边啊,因为需要关,或许等于GBCU,求点GA。Get connection OK,该事物action.set out commit for跟绑定跟绑定,因为我后边我还需要取,所以说的话呢,这个绑定的话呢,我们借助于第三个类进行绑定,Band。绑定过来看,我来写一个里边写一个吧。叫connection context。这里的话呢,我需要一个。
23:15
等于六。什么来的logo好了,写完之后的话呢,我们要写两个方法,第一个。Public band跟线程绑定。传入一个。怎么绑定啊,直接connection.size。好了,获取发布一个avoid get avoid获取链接。好了,获取链接直接connection由。
24:05
Local点还有一个解除绑定public幕移除,怎么移除?哦,这样写ad next点笔幕,它有一个方法。咋写的,看看帷幕怎么写的,是不是把这个this遗图就可以,这个this是谁啊,当前的select local他他是注意哈,它是把这个放到什么呢?放到了,放到了我那个线成的一个map里边,这个很重要,所以说的话呢,这个应该是一个单实例。Previous。Connection that local。啊,可能是,但是。
25:05
Private a de national contact。等于六方半的。然后呢,后来有了这个以后,我们到这个叫绑定。Connection。Get,绑上了,绑上之后过来。操作提交事物点回滚。connection.low back。
26:00
Try catch。关闭,关闭之前应该先解除绑定啊,七解除。绑定,然后关闭链接。怎么解除啊?叫connection,点目,点目然后。Did me.release写完好了,这个写完之后的话呢,因为我在这块啊,我把这个线程给绑定了,我把这个connection绑定了,所以说哪个呢。我们来看我们的。被子DAO。这。打开connection就不需要这么痛苦了,是吧?
27:03
咋写啊,我也不需要了。也一样。Did you see what?这是第一个方法啊,第二个。这样关的事儿不用你管。对,一样。这个。嗯。
28:00
保存好了再看。再看的话呢,我们来看我们的service。抄扑个林,我们看这个时候是不是回本了。应该一个也进不去,就是说这个这个也不改,后边的话呢,也不会出问题。讲。查接。嗯,注意啊,一本书卖四九十六。好了,出问题了,我们看。坏了。是不是改了呀,不然你没行啊。咱不说你要给我出问题吗?他说大家看这个异常了,同学们经常会发生这样的事啊,你看这个异常,这个异常这块的确是个by zero吧,这没毛病吧。
29:07
Zero,然后呢,80行。有。这块料的80行,然后七十五行,你看除了吧,穿完之后我们往往后翻,大家看我这个异常的确是抛出去了吧,啊这个异常不是吗?抛出去了,那这是给谁调的呢?这是给service调的吧。So。四类调到哪个呢?啊,调到这个开方法。好了,那我要是调这个要是出异常的话,应该怎么办呢?按照我目前这个情况,他应该是在这个filter filter呢。刚才写的。啊,我们的想法啊,它应该是在这个filter里边,这不是吗?我是调我先把这个东西去一去啊,太多了。
30:03
回来你看我往后传的时候出异常了,那这块出异常我应该能够捕获到啊,但我刚才没看着,那我我当我这一行往后走的时候,到哪呢?应该到我的SOSO,应该到这一行。好吧,到这一行啊,应该会出异常,这样一出异常的话,那他应该是执行到底。七十五行,就是这一行执行完了的话,应该怎么呢?应该把异常抛到。抛到我们理想的这个位置,不过刚才这个很明显没看着。郑红帆。跑一下吧。他为什么会把这个异常给捕获了呢?回退回退回,嗯。加15还是这一本的话,那是五五九十五了,过来看啊,这个过这个我们不需要看,每一次都会经过它。
31:08
查看你每次都经过他。就是正常走了,现在他没有输入操作吗?结账都经过他,我知道问题在哪来帮。来一好了,看这这个。这里好吗?注意往下。除以零吧,再回来。好了,我断了多轴说明什么呢?它说明根本就没走这个60行,为啥呀为啥呀,能想起来吗?那我一定是把这个异常偷摸给抓了吧?那你看我上面是不是用反射到的这方法,我这块我是不是catch,这个catch这个catch就是说我上面执行这个异常的时候,我这块是不是自个儿抓了,我没没往外流,所以说出问题了。
32:12
这个异常我们用外抛。One time exception。Exemp d。好贝。他会自己存下来啊。好了,回退。每一次呢,还会这样,这样一个。过。这个没毛病。再来查看,继续过,因为每一个都需要经过这个filter。
33:00
结账。再过好了这块我们我们想看的,汤姆1SUM看着这一行往后调,给谁了,给到了我的这个。除以零大家看都跑这来了,这个时候进行回滚了,你看这个多少。六九十四,因为刚才我又更新了一次嘛,就就不说你往后看了。嗯,下一个是不是back了,没毛病了,所以说这个时候就不会出问题了,再回来。注意看这个啊,这六九十四,嗯。回退回退。局高家查看结账钢笔。
34:00
是不是还是这个啊,这就很好,那这里面有个问题,那出长了,你给我页面怎么响应啊。怎么响应啊,这个时候就告诉你一声是吧,我不有future吗?我filter这个出异常了呀,于是哎,回滚了,然后告诉这个页面吧。Response。换。为啥不行啊,我上面是不是是不是HTTP啊。So response等于response。旋转一个,然后呢,Response send。喂。Request get context。女筷子也不行。等于你看。
35:05
来request.contact加登录下的error叫JT,就这个时候呢,我们去一个页面啊,告诉他你几的页面不存在或操作错误。二说一吧,就去这个地儿了。Four。我操作啊。哦,保存。行,你看。不退,不退。加。结账看汤姆一好。出错了,这样就解决问题了,那我如果要是没有这个。
36:01
Local跟这个filter的话,是不是就会导致了第一个成功啊。这个很显然吧,就是大家现在去做这个实验的话,就会导致了第一个成功,因为这个时候的话呢,我多个DAO用的不是一个connection,而我现在的话怎么样呢?我多个我多个DAO用的是一个connection,在这呢。多个DAO用的是一个connection好了,那这样的话呢,这将导致我整个这个测试方法都需要改,我找找一个啊不Gao,比方说get跑不起来了,你看。跑一下。是跑不起来了,因为这个时候出现了一个控制异常,他没有什么呀,他没有connection。Connection没有,所以说不行怎么办呢?我要想完成这个测试方法的话,我必须得先往那个嗯,在的入口里边放一个connection,你写一个吧。
37:06
那么写connection connection等于GB点,然后connection contact.band get band这回就可以了,再看。你看这个时候这个值是正常清楚吧,哎,这就是我整个local跟filter起的重大作用,回过头来再回顾一下,先看这个图。我这块的话呢,有一个大的filter很牛,我在发请求之前。干这样的两个事,获取链接,跟当前线程绑定,开事物,然后往后把这个什么,把这给到service,再给service,再到DAO,你无论怎么调的话都是一个connection,然后呢,当我调用的过程中,如果要是出异常的话,回滚事物,没出异常的话,提交事物在或链接就可以,然后呢,我在这个DAO里面,我可以从同一个select logo里边来获取我的这个。
38:16
Connection,这就是我们整个用跟filter完成事物处理的一个基本原理。往前翻。Select local是怎么回事?Select local呢?它把这个变量啊,实际上是放到了线程里面,我每一个县城里边有一个卖。他把呃,Local set那个变量那个引用放到了这个map里边,因为怎么了,因为我每一个线程是不是有不同的map啊,所以说我把这个变量放这个里边了,那我当然是安全的。那见是谁呢?见是对象本身。这个我们看源码的话呢,已经看得很清楚了,关于selectad local的这个解释在这块,那select local最常用的就是按线程多实例的对象进行访问的时候,我们就用带的localo,就是多个,每个线程对应一个实例,你就现在有时是吧,我每一个线程对应一个connection,就用select local,我们后边在讲harmles的时候,Harmlet里边有一个管理赛的方式叫select local,也是这个基本原理。后边的话呢,讲harm的时候呢,我们会看到跟这个写法几乎是一样一样。
39:35
OK。
我来说两句