00:00
Hello,大家好,今天呢,带大家来学习Java并发编程中非常重要的一个知识点,线程池。先。线程式是什么呢?首先的话呢,它是一种迟化思想,这种思想的话呢,在我们Java编程中啊,使用的非常普遍,叫磁化思想,因为它后面带一个池字嘛,对不对,类似的磁化思想还有哪些呢?比如说我们的这个线程池,当然算一个啊线程池。还有呢,字符串常量池。对不对,包括还有数据库连接池,相信大家对于这些概念都是非常了解的啊,这三个的话呢,就是一个典型的迟化思想,迟化思想它是优化程序的一种重要方式,它可以提高资源的利用率。它可以提高资源的利用率,那么线程池顾名思义呢,就是对线程对象的一种优化,如果说我们不使用线程池,那么我们对于线程的操作呢,就是第一步需要你手动创建线程对象,第二步去执行任务,因为线程肯定是要去执行一个任务的。
01:16
执行任务第三步,执行完毕,执行完毕干嘛呢?是释放。这个线上对象对吧?这样的话呢,它的资源利用率就很低,就相当于来一个任务,我来创建一个对象去执行,你执行完之后我把这个对象给它扔掉,然后再来下一个任务,我又创建一个新的对象去执行,你执行完成之后我就给它扔掉,对吧?效率就非常低啊,就相当于你比如说你打电话啊,你现在要打一个电话,然后你买个手机,打完之后把手机扔了,然后当你要打下一通电话的时候,又买个手机,打完之后又把手机扔掉,对吧?那肯定是很浪费钱的一种方式嘛。对吧?那么我们是不是应该买一部手机,然后去重复去利用。对不对,那这边也是一样的道理啊,不要说来一个任务创建限制对象,执行完了之后给它扔掉,我们应该让这个线上对象可以重复去利用,可以去执行多个任务,对不对?那这种方式怎么去实现呢?我们就可以通过线程池这样一个机制呢来完成啊。
02:11
所以呢,我们使用线程池之后的话呢,它的基本思想呢,就是预先创建若干个线程对象,然后放到缓冲池里边,我们来画张图啊,这比如说是我们的缓冲池,好现在的话我们就创建很多个线程对象放在这儿,比如创建三个放在这儿,好这时候当你有一个任务来的时候,我从线程池里边拿一个任务去执行,执行完毕之后呢,怎么办呢?给他还回来,还回来的时候是不是供下一次任务去使用,所以说假如我们同时来了四个任务。对不对,同时来了四个任务,OK,那这四个任务的话呢,这三个就足够去使用了,第一个拿一个拿走,第二个拿一个拿走,第三个拿一个拿走,这个时候他,诶第四个这时候暂时没有,没有的话怎么办呢?别着急,你在这排队嘛,等第一个任务执行完成之后,把这个线程池还原回来,把这个线程对象还原到线程池里边之后,你是不是再用它去执行任务就可以了。
03:01
所以说通过这样一种方式,我们就可以去提高咱们线上对象利用率啊,就是说我们这三个线上对象就可以处理很多个任务,只要说你这些任务呢,它是可以去排队的,不要说同时过来啊,不要同时并发过来,那可能我们需要去给他采用拒绝策略,要去排队的,对吧?那这边排队的话,就涉及到一个这个等待队列啊,就是说如果同时过来三个,好,那现在第四个任务过来之后的话,他这边没有没有空闲的线程让他去使用,它就可以进入到一个等待队列里边去进行等待。啊,在这儿就排队。排队,给他放到这里边排队。是吧,我们多画几个,比如说这时候来了五个对吧,三个去用,然后这三个用完之后的话呢。这时候你用完之后,好,你把它释放回来,你用完之后你把它释放回来,这时候是不是这两线程又是空闲的,空闲之后呢?是不是就让这两个任务去使用就可以了,这样的话是不是就可以做到一个资源的重复利用啊,对吧?这就是线程的线程池的一个基本的思想啊,那么线程池的优点有哪些呢?我们这边简单列举一下电能池的优点。
04:07
第一个是可以提高咱们线程的利用率。对吧,第二个可以提高。这个程序的响应速度。对吧,因为我们线程对象是提前创建好的,并且使用完成之后呢,也不会去销毁,那么这样就节省了创建和销毁的性能消耗,就可以提高咱们线程的运呃,提高咱们程序的运行速度啊第四点第三点是便于统一管理这个线程对象。对吧,第四点的话呢,就是可以控制最大的。并发数啊,这点怎么做到呢?我们可以通过设置线程池的参数来控制线程池的容量,进而控制系统的最大并发量,对吧?那接下来我们来说说啊,这个线程池的基本原理就是它首先呢,会预先创建一定的一定数量的线程对象的放入到缓冲池里边,好就这样的来我们这边。
05:08
再来画一下这个,哎。这边都是任务啊,先给它去掉。比如说下三个。发现三个之后的话呢,你这边任务过来之后,是不是从里边取对不对,那假如说同时来了四个任务怎么办呢?四个任务的话,是不是肯定只能执行三个任务,那剩下这第四个任务怎么办?他就需要进入到等待队列,就在这队列里边去排队啊排队等这边哪个线程哪个任务执行完了之后,把线程释放出来,你去执行就可以了。对不对,但是呢,我们如果说同时来很多个任务怎么办呢?我们这个队列它也是有长度限制的,比如说我们队列就两个对吧,也就是说最多是不是这俩这边能排俩人啊,有最多同时我们能处理五个任务,这时候如果来第六个的话怎么办?这时候你也进不来队列了啊,这边你也执行不了怎么办?这个时候呢,县城,我们这个县城省呢,它就会启动一种这样一个应急处理的一个一个预案。
06:05
对吧,这什么叫什么叫应急处理的预案呢?就是说他发现这时候并发量很大,我们现在这样一个状态,已经没有办法去满足这样一个状一个并发量了,怎么办?这时候它就会创建新的线程对象,创建一个新的放里边,诶这时候是不是多了一个线程线程对象,那这时候你是不是去执行就可以了啊,他去执行嘛,然后你这个往前排一下,你这边是不是再进来就可以了。对不对啊,他是可以去再创建新的限制对象的啊,那假如说这边又来一个任务怎么办?那我再创建个新的不就行了,对吧,然后你去执行。然后你去往前排,你去往前排对不对,但是的话呢,我们不可能说无限去创建这个线程对象,因为我们这个线程池它的容量是有限的,它会有一个最大线程数,最大线程数指的就是我们当前这个线程数里边能够容纳的最大的这个线程的一个个数,假如说最大就是五个,这时候已经到达顶点了怎么办?假如说又来了一个新的任务啊,这时候怎么办呢?那我就只能拒绝你了,因为你这个队列也进不来了,然后呢,也没有空闲线程对象了,我这个线程数量已经达到最大值了,也不可能再创建新的线程对象了,所以实在是不好意思对吧,没有办法处理你了,只能把你怎么样拒绝掉。
07:13
啊,要么直接抛一场,要么让其他线程去执行它,总之呢,我就我这个线程是处理不了了。对吧。那这个的话呢,就是线程池的一个基本原理。我们刚才说这个概念可能不太好理解啊,接下来我给大家举个生活中的例子,你马上就能明白。大家肯定都去过银行营业厅去办理业务,对吧?那么银行营业厅呢,就是一个典型的限能池的模型啊,我们来看这张图。看这张图啊,对吧,这就是银行营业厅这个模拟图啊,我们这边是有柜台的,然后呢,柜台里边有五个窗口对吧,这边等候区就是呃,人多的时候你排队在那坐着对不对,然后的话,我们一般这个窗口呢,它不会全部打开的啊,假如说我们今天就开三个,然后后面这四五的话,我就给它关掉啊,红色一本表示他今天没上班。对吧。
08:00
比示他没上班啊,OK,好,那现在的话呢,假如说第一个客户进来,那是不是在这儿去办理啊,同时进来俩是不是一二,同时进来三个是不一二三没问题吧,同时进来四个怎么办?诶第四个人一看,诶前面三个已经被人占了,我是不是在这等一会儿就OK了,对吧?等一会儿假如说二号办理完了之后,你是不是去二号办理就OK了,是不是这么一个概念,是不是跟线程池一模一样啊,对不对,这是不是就相当于我们的线程池里边的线程对象,这边是不是相当于等待队列,明白那意思了啊,假如说同时来五个,OK,那这两个坐着等呗,同时来六个,这三个坐着等。没问题吧,好,如果说同时来七个,哎,这时候第七个人他也没地方做了,对不对,这边也没有办法去办理啊,这时候行长一看,诶说今天这个客流量比较大啊,所以说这三个柜台呢,已经没有办法去应对我们的一个并发量了,怎么办?那第四个人赶紧回来上班吧,对吧,你也别在家歇着了啊,回来上班来这个打开。OK。对吧,把它打开啊,打开之后的话,你看这个时候第一个人是不是就这样办理,然后他是往前往前挪,往前挪,你是不是来这儿等着就可以了,所以这样的话呢,这七个人是不是都给他安排好了,假如说这时候来第八个,同时来八个怎么办?这时候行长一看,诶,今天这个真的是生意好啊,所以说第五个人你也别歇着了,是不是回来上班了,对不对,给你打开,OK,这样的话他来。
09:21
好,他往前走,往前走,往前走。是不是这么一个状态,对不对啊,这时候就已经满足我们的需求,这个时候假如说今天又来了一个人,同时来了九个人,这时候怎么办?一看啊,实在是没有办法了,我们这边这个柜员是不是都已经回来了,对吧,我们这123455个柜员都经回来了,然后我们已经没有新的地方了,就算我现在想再让一个柜员上班,他也没有地方去办理这个业务了,所以所以说这边肯定是不行了,同时这边等候区是不是也已经坐满了,你实在没有地方待了,我就只能怎么办了,说不好意思,我们这个网点。不能办理业务了,您去下一个网点去办理就可以了,对不对,是不是就相当于采用了一个拒绝策略啊。
10:02
没问题吧,所以说这个银行的营业厅呢,就是一个典型的线城池的一个思想,OK,那我们这个县城池呢,它是非常灵活的啊,就假如说啊,今天一今天早上生意非常好啊,同时来了很多人,这五个人全部上班了,好,但是下午的时候呢,诶,人没有那么多了,对吧,下午大家可能都集中早上办业务啊,下午的话没有这么多人了,假如说下午的话,我同事来了。三个人。对吧,就是同时我们营业厅他最多同时容纳三个人,这时候这俩一看,哎,说你俩这个好像又待着有点闲啊,对不对,你你你又没有去办理业务啊,那算了,你俩还是回家吧,对吧,所以说我又可以把这两个怎么样给它关掉。啊,又可以把它把这两个关掉,所以这就是我们线程池里边一个非常重要的一个概念,叫做存活时间啊,就是我们如何去判断一个线程是否要存活,就是判断他在一定时间内有没有去接到这个任务,如果说没有的话呢,我们就直接给他销毁了,因为不需要他了,对吧,不需要去创建那么多线上对象,三个足够了,那四五就可以回家了。
11:01
OK吧,就这意思啊,所以这个就是我们。这个线程池的一个模型啊。好,那么我们把这个模型讲完之后呢,接下来我就带着大家呢,一起来通过代码去实现这个模型啊,非常简单,来,我们打开代码。我们在这呢创建一个类。那我们这个线程对象怎么怎么去创建的,线程数对象怎么去创建的啊JUC并发工具包呢,给我们提供了一个。这样一个类,我们通过这个类的话呢,就可以直接来创建我们的这个现制式对象了啊,它叫做thread pro exter这么一个类,我们这边直接扭一个。THEX就可以了。对不对,然后这里边呢,会有这么七个参数,每个参数都有它自己的意义,来我们来一一起来写,第一个是核心线程数,核心池的线程数就相当于默认的这三个人三个柜台三,然后第二个的话,就最大线程数是不是最多就五个窗口,所以第二个是五啊,第三个就是存活时间,就我们说哎,如果说你长时间没有去接到任何的一个任务,你就可以下班回家了,对吧?比如说我们设置一秒钟啊,一秒钟,然后这个第四个参数是它一个时间,因为它有时间单位嘛,懂吧,我们用秒啊,一秒钟之内没有任务,你就可以下班了。
12:24
对吧,那第五个参数什么呢?第五个参数就等待队列嘛,相当于这来我们又一个。A block you。然后呢,呃,长度为三吧,好,然后。那第六个参数什么呢?第六个参数的话呢,就是我们的这个。呃。线程工厂啊,因为你通过线程工厂呢,去创建线程对象,这个线程工,线程工厂的话,我们不用去自己创建啊,直接调filter里边的有一个叫defaultread factory就可以了,这是线程池线程工厂啊,最后一个的话呢,拒绝策略,拒绝策略的话,我们这边使用一个默认的叫above policy,就直接抛异常的一个方式,OK,我们把它创建出来之后的话,我们来。
13:10
去接收一下。接住它啊,这边我们用这个。用excu service去谈去接收,直接可以去调用的啊service啊,现城市创建好之后,接下来就相当于我们这银行这个布局有了,有了之后我们就可以去接待客户了,对吧,我们这边假如说先来一个客户啊,所循环走一个同时来一个客户,然后这边的话呢,从线程式里边去取一个建争对象,就Q的方法,这边用拉姆达表达式去写我们的执行的业务啊。这边的话呢,怎么办呢,就是办理业务呗。把这个现成的名字拿出来,Get name。这个人在办理业务。OK,输出对吧。然后执行完了之后的话,我们需要把这个线程池啊,给它关掉,刷到好了,直接来启动,现在就相当于来了一个客户。
14:07
对吧,我们可以看到第一个线程是不是在办理业务,如果说同时来俩,是不是应该是一二。一二在办理业务啊,来走。没问题吧,那如果说同时来三个,是不是123在办理业务啊。看到没有123啊,如果说同时来四个,那这时候是不是123去办理四个,然后这第四个人在这先等一会儿,但是也是123去办理四个业务吧,来走。OK,没问题吧,你看是不是一办两次,二三各办一次,OK,那如果说来五个人,是不是也是123办理五个业务。来做。我们可以看到啊,是不是二和三分别办理两次,然后一办理一次,就相当于是这么一个状态吧,明白吧?啊那如果说同时来六个的话呢,是不是123办理六次业务。
15:11
看到没有?是不是各办两次?对不对,各办两次啊好没问题吧,那这时候如果说来第七个人的话,同时来七个怎么办?诶,这时候行长一看,诶。这边也没地方待了,对吧,这边也办不上怎么办?赶紧让这个人赶紧回来上班吧,对吧,今天你也别休息了啊,咱们今天这个业务量比较大,你回来吧,回来之后呢,诶,他是不是就可以办理业务了,所以说现在是不是相当于1234去办理七个业务。来走一下,看一下1234办理七个业务,你看你看这个结果。没问题吧,1234办理七个业务,至于说谁多办谁少办,那是他们的事儿啊,至少说我们一定是可以确定是1234再办理七个业务,OK,那假如这时候又不行,又来了一个怎么办呢?啊,这时候又不行了怎么办?那你赶紧回来上班吧,对吧,你也回来上班,这时候是不是12345全部上阵,然后办理八个业务。
16:07
没问题吧,12345全部上阵办理这八个业务,假如说这时候又来了一个,同时来九个人怎么办呢?这个时候就已经到达了我们银行的上限了啊,就算我想给你再调柜员过来,他也没地方待了,对吧,柜台最多就容纳五个五个人对吧,这边你来一个人,来个柜员,他也没有办法待了,就相当于我们这个县城池是不是已经到达它最大最大上限了,这边没有办法去给你,给你。来一个现实对象去办理你的业务,这边等候区也没地方做了,怎么办呢?那您是不是只能去其他网点去办理了,我们这个网点已经到达我们的上线了,没有办法去接待客户了,是不是您只能去其他网点办理,是不是直接给你拒绝掉了?没问题吧,来这边我们模拟一下,同时来九个的时候走你。对吧,我们可以看到直接抛了异常出来啊,直接抛了异常出来,这时候就采用的是我们这个拒绝策略啊,这个拒绝策略是直接抛异常的方式,我们也可以采用其他的拒绝策略,这个到后面咱们再详细去说,对吧?但是我们现在可以看到同时它可以容纳多少个呢?同时可以容纳八个,因为我们的最大线程数是五。
17:15
对吧,然后呢,我们等待率是三五加三,不就八吗?最多可以容纳八个客户,五个人在办理,三个人在等待,但是如果说同时来九个就已经超过我的上限,那就只能拒绝了,对不对。拒绝策略,我们这边默认的使用是about policy,至于其他的拒绝策略的实现的话,下节课老师再给大家做一个详细的讲解。好了,以上就是关于线程池的讲解,那通过学习本节课程呢?相信大家已经对线程池的基本概念和使用有了一个非常好的掌握,如果你想继续深入学习线程线程池的相关内容,那就不要错过老师的下节课程了。好了,本节课内容就到这里结束,感谢大家的观看,拜拜。
我来说两句