00:00
下面我们分别为大家来讲解两种形式将任务添加到异步线程池的方案,第一个方案呢,就这样子的处理耗时业务,将这个处理耗时耗呃耗时业务的这个任务。咱们。同在handler中把这个任务加入到线程池里面去,当然是异步线程词了。第二种呢方式就是在contact中添加线程词,就是把这个在contact contact中把我们这个任务添加到线程池里面去也可以,那现在呢,我们对这两种方式分别进行一个阐述。打开我们这儿准备好的文档,一边讲咱们一边分析。首先呢,给同学们看到。对,我们先讲第一种方式,那第一种方式呢,我们看到还是需要对原先的,就是现在现有的A口这一个源码进行一个修整,它是它的方案是什么样的呢?就说相当于在我们这个handle格中,直接先定义一个什么呀,定义一个线程词,像这个线程词是什么呢?叫做devote event exor group。
01:10
它充当的是什么呢?充当的是业务线成词好,同学们,我们给大家写一下。首先呢,它一定是个静态的啊,也是也就是说它是可以被所有handle共享的,这个能理解find类型的,然后呢,我们就叫。ET,这个在我们前面讲过的group是个组。Group。等于另一个什么呢?真实类型debt。也就他了。然后呢,我们定义16个。我这里呢,做一个解释。什么呢,Group?Group就是业务线程时充当这样写充当。充当。充当业务线程次。
02:01
哎,干什么呢,现成尺。可以,可以将任务将任务。任任务提交,提交到什么呢?该线程池中。OK,那么我们这个线程有这个线程池里面有多少个线程呢?有16个,因为我这写的是16。这里我们开的是16个。这里我们。开辟了或者是创建了。创建了16个线程。对不对,16个线程这写的好,那么我们接着往下走,接着往下走,那首先。呃,我们在这里下一个断点,同学们看。下个断点,如果我在这下个断点的话呢,我们看这个group,其实它会怎么样呢?它就会有16个子线程,我们来运行一下。同学们,我们先把这个停掉。没问题吧,先停掉。
03:01
好的,那停掉以后呢,停掉以后我们先来启动它一下。没问题吧,启动我们server。诶,不好意思,我这边用debug的形式。找的没来。呃,这边呢,我们我们在处理异常的时候,干脆这个信息就先不去打它了。因为我们这边这边是直接关闭关闭程序的,一般都会发生异常的,所以说现在我们把这个信息先不输出了。停掉,停掉过后呢,朋友们,我们debug。我们先来看一下,就是给给同学们看一下,刚才我们创建的这一个event,就是叫event group,它到底是个什么东西,这个地方先要给大家聊一下,来朋友们运行让一下。好的,那代码会定在哪个位置呢?第八个到这来了,好,我们来看看group是什么。
04:01
同学们首先看到它的类型,就是default eventor group里面有char子线程有多少个,16个,而每一个子线程又什么de报TE event exor了。诶不再是group了,它是Q的里面下下面的就是我们相应的任务,诶你看这边是不是也有它是个Q啊等等等等等等,这个能理解吗。好的,那一共有16个哈,一共有16个,好,那明白这个道理过后呢,我们接着继续往下走。下面呢,我们准备怎么办呢?这个任务不这样提交了,我们要换一种方式来提交,那现在呢,我们来写写怎么来做这个工作。那我先把原先这个方案怎么样注销了,这个能理解吧,先把原先这个方案注销。好的,这边都注销,注销完了过后呢,我们来这样编写。哦,就是刚才我说的将我们的任务耗时任务。
05:00
将任务提交到县城市。将任务提交到线程,哪个线程池呢?就是同学们看到的group。这个时候他的方案是这样子的,同学们跟上我的时候,第它本身就有个submit的方法,然后在这里呢,我们直接给它传入一个实现了coll接口的匿名。对象。怎么走你?好的。那这个时候我们怎么写呢?这个大家都知道,它是一个接口。Interface接口,它这个接口里面有一个call方法需要我们去实现,所以说呢,这个方法我们必须予以实现才可以的。好的,那现在呢。这边来坐下。OK,哪一个方法是靠这个方法。好,那在这里面呢,我们就可以把任务写到这里面去,OK,那把任务写到这,那么就这样写哈,比如说我们这边这个任务呢,是这样编写的,我们首先拿到这个MSG,因为我现在想看一下客户端给我发送的消息是什么,是不是我可以想在这接收一下来吧。
06:14
我就简单简单一下接收接收客户端信息消息。那我就这样写了,跟原先的思路非常的相似,先拿到这个BAT buffer。OK。那这边我们就写个buffer,对于什么呢?Mst转一下。对,转了以后呢,同样我们还要创建一个什么呀,BAT数组。这个BY数组呢,就是buffer,前面已经写过了read。Read。BAS,好,拿到,拿到过后,朋友们。来生成一个bitt数组,Bit数组我们就叫BY吧,接着继续往下写,那现在这个BY数组过后呢,读进去。
07:01
Red fights。放到把数据放到我们的bit数组里边去就是。这个字节数组,然后这个字节数组过后我们该干什么呢?六一下对不对,六一个菌。那个十句六个十句呢,内容就是我们这个拜词。转成按什么编码呢?就UTF杠八即可。拿到了,拿到现在我们就拿到了这样一个消息,我们叫body吧。拿到拿到过后呢,下面呢,我们想休眠,比如说我们这个很耗时嘛,我们认为这个很耗时,所以说我休眠。休眠多长时间呢?十秒。没问题吧,休眠十秒,那就sh.sleep。OK,那就是十乘以1000。然后呢,在这里我想把当前这个工作的哈,就在这个submit这个里面去,就是call这个方法里面,它到底调的是哪个线程信息输出来来走一个。
08:07
没问题吧,我这样写就是说group submit。的。哪个呢,Call这个方法。的线程式,对是哪个线程执行它呢?线程式输出加上。点。current.get我要输出这个信息,输出这个信息以后呢,我想给客户端回复一个消息,还是回复喵喵喵,好,那我怎么回复呢?非常简单,那我就这样写,先把时寸写好。这不是有吗?是不是?OK,这样给他回一个哈喵喵喵就可以了。就是用ctx right and flash,然后hello,客户端喵喵喵,然后编码是按照UTFUF杠八给它发送回去,下面这个做完了以后,同学们下一步该干什么?Return,因为他他这么要求我们返回,有一个返回这呢,我就return一个空,我暂时没有返回值就空。
09:11
好的代码就写完了,那现在呢,同学们看,这是一种提交任务的方式,这又是一种提交方式,那现在我们要看一下此时此刻该线程就这这个里面的线程是哪个在执行而。我在上面又打了一个handler的线程,是这我们看这两个线程还是同一个线程吗?可以告诉大家,肯定不是了,我们来运行一下看看。我先关闭这边好吧,这边。啊,这边已经停止了,那现在呢,我们运行就可以了,朋友们运行。跑起来。跑起来。好,Server端。一抛弃了高端。看这边同学们。首先我们看到这边handleler的线程是NL event group group3杠一,对吧,而且呢,大家看到也确实没有阻塞,因为它直接就输出了go on,好,同学们看,在靠这个线程里面呢,它是default event group4杠一,也就是说实际上是我们的这一个线程。
10:20
这个线程池里面的一个线子线程,但是哪一个呢?同学们可以看光标可以,当然我们可以把这个光标停在这,其实就是它的第一个。其实就是他的第一个,因为我这没有,呃,没没有下断点哈,那如果同学们我问大家,假如我在这地方再起一个客端。来运行一下,同学们看。又骑起来,骑起来过后呢,我们再来看此时此刻又会出现什么情况,大家看还是他进来的时候还是掉handler的。这个还是这个线程就是n l group3杠一,为什么又是三杠一三杠二呢,这边。哪个同学能告诉我?是不是因为你本身在这个e server也是起的有有worker group里面是不是它它也有,呃,有八个直线层呢,相当于说它是这样来分配的。
11:12
就是你第一次?这是我们的Bosch group。Bos group连上logo呢,把你这第一个请求分给了我们这个。IO event loop,就是这个IO event lo io3杠一我简写,而这里面呢,它又在你的这个call里面呢,又在这里面把线程分到了default。Default。这个四杠一这样来的,第二个请求来了过后呢,他仍然是从Bo boss这边来的,第二个客户端来了过后呢,他把你这个请求分改了NIO的,NIO的三杠几呢三杠二,而这个三杠二里面呢,它又从这个静态的,就是从这个静态的。呃,我们的线业务线程组里面把debt什么呀,Debt。
12:04
这个四杠二给你分配过去了,就这样子一个逻辑明白好,那现在呢,明白了过后我们大家如果我再来执行一下,他应该是怎么分配。能能告诉老师吗?好,如果不出问题的话呢,他应该也是按照这个流程来分配的,下一个就应该是三杠三了,果然。三杠三,那这个地方goon打出call应该是什么呢?就是default event a4杠三没有任何问题。就这样一个逻辑,所以说通过这个案例呢,我们可以看到,我们可以看到此时此刻哈,此时此刻在我们的这个server端。他在提交这一个任务的时候,耗时任务的时候,他已经不是跟你当前这个handle线程是同一回事了,那同学们可以这样再试一下,我们现在关闭一下,我这次多提交几个,你看他这个时候呢,很有意思,我直接关闭。说哦,那同学们看我在这儿多提交几个哈。
13:02
也提交了一个两个。三个。我我在这里呢,提交了在,也就是说我在这个handle里面呢,像。他的线线这个业务线程池里面提交了三个耗时任务,而这三个耗时任务呢,他应该是从我们这个业务线程池里面去一个一个分配的,看一下是不是这样子。好,我们就直接运行即可。Run。待会我们再讲它到底是怎么实现的哈,来看一下。跑起来,然后呢,我直接运行。好的,那这边呢,应该会接收到三个回复。好,第一个三杠一还是三杠一,他选的是我们worker group里面的三杠一这个子线程为其服务。下面看是不是。123。是不是样子的,诶,也就是他这面按照按照这个流程给你分配的,那这边应该接收到了三个回复,好的,就这样的一个道理。
14:05
同学们,那关于这块呢,我们继续来阅阅读它的。其他部分。那么这样做了过后,他到底做了什么事情呢?在China read中模拟了一个耗时十秒的操作,这里我们将任务提交到提交到一个自定义的业务形成池,就是刚才我们说的group。Group这样呢就不会阻塞我们ni的IO,而且它是个异步执行的,那这样处理过后,整个程序的逻辑它就变成这样子了,来同学们看一下这个图,这个图呢,有点小哈。我把这个给大家放大一点。看这张图。这张图呢,其实他把这个信息描述的比较清楚,他说socket。来了,So,这这边呢,呃,在这个IOIO这个线程监听到有一个比较耗时的业务,然后呢,走走走到这个out棒的时候呢,它会把这个耗时的handler提交到一个业务线程,提到业务线程过后呢,处理之后,他把这个业务线程处理完了过后呢,他又会交给IO线程尺的队列继续执行,也就是说大家要这么去理解。
15:11
怎么理解呢?就是进来的时候。他用的是。一个呃,这个worker group的某一个子线程,然后到这边执行的时候呢,大家看到他又怎么样呢,他又去使用的,呃,自己的业务线程池的某一个线程,回到这个地方,Ctx right and flash的时候呢,大家看这边这段的文本,看这里。当house任务执行完毕,再执行paperline right的时候,呃,代码里面我们写的就类似于这个玩意啊,就是这个就是right and flash绘制是会做什么呢?呃,他会将任务将会将这个会将任,诶这个什么会将任务,会将该任务吧。
16:00
会将该。时候。会将。会将这个任务啊,会将这个任务再次交给艾欧先生,又回去了,看到没有?看到没有,这处理完了,把你这个耗时任务处理完了后,他又重新回到了我们这个IO线程去执行,所以说他把耗时任务,把这个耗时的工作呢,交给了你的业务线程去处理。是这样的一个流程,好,那明白这个道理过后呢,我们再接着来讲下一个,下一种方式就是对它的源代码呢,我们做一个剖析,他到底在哪里去实现了这个异步操作的。来我们看一下,我来看首先呢,在这个write方法,这在这个write方法这有它的一个源码,这个源码里面呢,有一个非常重要的判断叫做exor in。Lo什么意思?我要看大家看你当判断下一个outbound的ex线程不是当前线程的时候,会将当线程的工作、当前的工作封装成一个task,然后加入到一个队列中,等待IO任务执行完毕后,执行队列中的任务。
17:15
那么这里面呢,我们可以用debug来给大家验证一下来同学们。那现在呢,我给大家简单验证一下啊。怎么走呢?我们直接把断点下在这个位置,下在哪呢?下在待会下在这个地方。朋友们。我先稍等一下,哎,我在这个地方呢,先给大家下一个断点。来看一下是个什么情况。好,我先把这个先停一下,停下过后呢,我先找到关键位置。我们搜一下就可以了。朋友们。找到他了,然后呢,我直接打开这里。好,那待会儿呢,我的断点就会下在这儿。
18:00
我的断点就会下在这个位置right了吗?啊在写的时候它是怎么去处理的呢?对不对,好,那现在呢,我们回到这边来,回到这边来,我们debug。我们debug一下。自信。好,第八个功能我们启动。我们系统可难。启动,可过后我们看一下他刚才针对那个图的一个解释哈。诶,这边不是第八个吗,怎么又。这边。好来了,因为他要过十秒才到这个位置来,抬到这个位置来过后呢,我们往下执行一步。好,现在呢,显然它不会进入到,不不会进入到if语句,它会到哪去呢?它会到这个else语句。看到没有?他会到这个else语句,因为你现在呢,这个AQ并不是咱们这一个当前线程的,就说我这说的这句话。
19:00
哪里呢?就是这里判断下一个autobo的AQ线程不是当前线程的时候,就会将当前的工作封装成一个task到这里来,那也说这个代码呢,会继续往下执行。然后执行这个CE。打开没有。哦,是这样一个流程,明白,那如果说有些同学老师,那假如呃,我们没有这样去加入他会怎么样呢?那他就不会到这个位置,他是直接进入到这个位置,我给大家再演示一下。来,朋友们。断点还下在这里,但是呢,我的写法。稍微的改一下,这次呢,我们这样写。我们就不用什么呀,我们就不用我们这一个提交到group的这种方式,我们直接把代码呢放到这里来。这是普通的方式,写到这儿,做一个比较普通方式。好的。那普通方式,诶,这地方会有异常哈,没关系,我先把上面这几个方,这提交的几个任务先注销。
20:04
同学们看我先注销了。没问题吧,注销这边呢,会有异常。这边会有异常,因为我没有补货,那简单一点,咱们这就先扔出去吧,好吗。先扔出去受死。扔到这里来,扔到这里来,大家看,此时此刻我相当于就按照普通的方式来处理的,那如果按照普通方式来处理的话呢,待会儿我们再追这个源码的时候,在追这个源码的时候,它就会直接进入到。这个IF1句里面去,那我们来看看是不是这样子的呢,来同学们,我们仍然进行一个第八个。仍然进一个第八个。好,我们看看这边还有没有需要关闭这个关闭一下。Debug这边。好OK,现在呢,我们进行一个第八个。跑起来。第八个,启动我们的ECO server。
21:00
然后呢,我们再启动。让一下,让我们的客户端等待十秒钟,等待十秒钟就会到达。我们下周断点。然后我们再进行判断。同学们看,现在我没有异步方式提交了啊,同学们看清晰。稍等来了,接着往下走。好,此时此刻呢,我们再次执行,它会进入到if一块,没问题,看到没有,进到这边去了,看到没有,它是next invoke invoke right and flash是不是这样子的,那你可以往里面走吗?你要往里面走。下面就一步一步调用了,这个我就不去追他了,好不好,所以说这里面的关键点就是在这个位置,他要不要形成一个任务来提交,就是我们这写的对不对,就说判断下一个out棒是不是,那么这里呢,这里这现在呢,我们就把第一种方式,就是哪种方式呢,就是我们现在讲的。将耗时耗时的业务啊在handle中加入到形容词。好,关于第一个方式,我们就给大家讲解到这里来消化一下。
我来说两句