00:00
大家好,我是海波老师,我们继续来讲Java语法中的线程,之前咱们讲到了Java中的线程对象啊,有六种不同的状态,那么其中这个新建、可运行和终止呢,是我们三个最基本的状态了,那么我们还有三个呢,叫主摄等待和定时等待,这三个状态呢,其实是从可运行状态进行转换得到的,那么我们通过调用对象的不同方法来改变和转换不同的状态,那为什么要给线程设定这么多的状态呢?那主要原因就在于线程是整个应用程序逻辑代码非常重要的一个执行载体,那么这个代码逻辑的执行过程啊,以及当前执行到一个什么样的程度呢?对于整个应用程序来讲其实是非常重要的,所以啊,我们必须掌握不同线程当前的执行情况,也就是执行的状态,我们是需要了解的啊,而这个状态呢,它会因为代码执行的逻辑变化而发生变化,所以每一个线程对于软件进程来讲呢,都应该有相应的监控程序来监控线程的执行情况,那么软件进程呢,就会根据监控的情况呢来。
01:00
才合理的调度和管理其中的线程,但是大家想一想,如果线程变得很多,那么监控程序的负担就会变得很重,对吗?那么软件调度不同,线程的执行呢,也会变得非常的繁琐,那么这样的话就会导致软件的性能受到影响,所以线程的创建数量啊,以及如何使用是需要提前规划好的,而不是说啊,我需要一个线程,我们就创建一个线程,那么这样的话效率太低了,而且会感觉杂乱无章,对不对?所以啊,为了简化线程对象的创建过程,以及合理使用和分配资源,Java提供了一种特殊的处理方式来获取线程对象,那么这个我们称之为叫线程池,我们这里呢,把这个代码呢给大家写上一下来,我们拷贝,拷贝以后呢,我写上一个我们的零五,然后呢,写上一个我们的铺。我们这里呢,我们复制一下,我们点击OK,然后呢,把我们这个名称替换一下,把这个全去掉啊,咱们都不要了,把下面的这些类呢,我们也给它去掉好去掉以后再写上它,我们叫做线程池,什么叫做线程池呀,咱们解释一下,所谓的线程池哎,其实它就是线程对象的容器,诶我们起上一个铺,诶,它是一个容器的概念啊,那么这个容器中的线程呢,它可以根据我们的需要,在我们启动时候创建一个或者多个,这里咱们也说一下啊来,它可以根据啊我们的需要在启动时啊我们创建。
02:27
创建啊,一个啊,或者我们叫做多个我们的线程对象,哎,就是这个意思了,Java中线程池比较常见的有四种方式,这里我们说一下咱们Java中。有啊,我们的四种。比较我们常见的啊线程池,诶好了,来我们说第一种啊,第一种就是创建我们叫固定数量的线程对象,诶这个是什么意思呢?就是我现在有个线程词对象啊,那里面呢,我就固定创建我们的几个线程,就这个意思,那这个怎么写呢?我们写上它叫ex,诶有这么一个类啊,叫executors啊加个S,它里面呢是Java u concurrent这个包里面的啊,那么这个里面呢,我们点一下它里面有个叫new,叫fixed thread pool。
03:17
A是一个固定数量,那么这个数量呢,我就在这个位置给它写上就可以了,写完了以后我点一下,诶VR回车,回车以后大家会发现它会返回一个叫ex service,这个呢是一个我们的服务对象,它专门是用来提供线程服务的,这里我们写上它啊,咱们叫做e service,它是我们的线程服务对象,哎,就这样的,那好了,那我怎么用它呢?哎,这里咱们给大家讲一下,我们这里啊给大家画一个小圆圈啊来表示这个对象,所以呢,我们拿过来。拉过来以后呢,给它拉大啊拉大拉大以后呢,我们这里呢,给它来,我们写上一个蓝色吧,哎,表示一个容器的意思啊,咱们它呢,就叫线程池对象来,怎么着写上它,把它去掉。
04:03
然后呢,我们这里写上啊,咱们叫线程池对象,OK,然后呢,来好了,放过来了以后我说过了,我们这里有一个什么呢?固定数量的一个概念,就是说它要创建三个线程,那所以这个容器当中啊,我就准备三个线程了,所以呢,我们再画圆圈啊来我们的第一个这个呢,我们给它一个我们的绿色,诶好,然后呢,写上一个叫T1,它表示我的第一个线程,那么总共有三个呀,注意拷贝。我们这里呢,有一个T2啊,咱们写上它,我们叫T2,然后呢,我们这里呢,我们再来复制,我们写上它叫T3好了,写完了之后呢,我想用它,我怎么用啊,我这么用,我现在呢,我们画一个小人啊,咱们的用户咱们拿过来。这个用户呢,我现在想利用咱们的线程啊,执行一段逻辑,记住我想利用线程执行逻辑,那么这个时候我就要把这个逻辑代码呢,就要提交给这个对象让它执行,所以呢,我们的基本原理呢,就是说我现在想做一件事情,诶这个事情我先有,有了以后我把它提交到这个线程词对象中,找到某一个线程让它执行,所以咱们这个黄色的这件事儿啊,诶拿过来,拿过来以后你会发现,诶老师啊,这有三个我让谁执行啊。
05:14
其实大家会发现我的三个对象都是绿色的吧,为什么我画成绿色呢?因为谁都行,那么好,咱们就假设我们就第一个,所以呢,我的箭头呢,就指向了我的第一个,为什么找第一个,因为它是可以工作的,所以把这个黄色的这个事儿啊,诶咱们提交给他执行就行了,这个过程呢,我们就叫submit啊,咱们叫提交,哎,把咱们的工作呢,提交给他,那么你提交给他以后,这个T线程啊,它就不能是绿色的,为什么呢?因为他正在工作吗?他正在工作的话,我这里给他个红色,表示繁忙嘛,正在干活嘛,对不对,就是这个意思。诶老师,那如果这个时候如果有其他的用户来了怎么办?比方说有第二个用户来了,第二个用户呢,他也有自己的工作呀,他也想提交给他怎么办?也就意味着如果我们也想提交的话,我也有工作,诶拿过来这个时候大家看一下我的颜色呢,就放这儿了,放这儿了以后你记住了,同学们,我现在呀,我们去提交没问题,但是你提交以后,我们能够工作的县程就不是三个了,为什么呢?因为这个正在工作,它处于繁忙状态,但是这两个还属于什么空闲状态,他们俩没干活对不对?所以呢,我这个提交呢,我们的线程池对象就会帮助你从他们两个选择一个,那比方说就选择他了,所以呢,我们复制一下,复制以后大家看一下,我复制把这个呢,我们拖过来,拖过来以后咱们指向他就可以了,诶那么我的工作呢,就提交过来,就走到这儿就可以了,所以啊,这是我的第二个用户老师,那如果有第三个呢,好,我先把这个放回去啊。
06:45
把这个放回去,给他一个红色的,然后呢,我们来再复制一个,复制一个以后呢,干嘛呀,我们也提交啊,所以咱们拿过来。咱们现在呢,我的第三个用户呢,他也来提交我的工作,所以把这个呢,我复制过来,复制过来以后我这里给他换个颜色,那这个时候怎么办,你会发现它里面就只剩下一个T3了吧,所以我们的这个工作就会委托他来执行,所以我们的箭头咱们拿过来。
07:11
拿过来以后,我说过了,我们委托这个线程来执行就可以了,啊把它去掉好,那么我们的箭头呢,我们指向它,我们就一步一步诶提交过来,你提交过来以后,同学们我的T3诶也就开始要工作了,他已经处于繁忙状态了,老师呀,那好巧了,我有第四个用户来怎么办?我第四个用户来,这三个线程还都在执行,没有执行完呢,那这个时候我们又提交了我们的一个工作怎么办?大家想想同学们,我们想想如果是你,你会怎么办啊,如果这个操作是你,你该怎么办呢?哎,把这个东西咱们复制,复制过来以后,把颜色呢,咱们稍微的换一换,换个紫色吧。其实我相信大家应该能够想得到,我们现在我们的线程池对象只有三个线程,那么他们三个线程正在使用当中,你这个工作就做不了了吧,哎,就做不了了,所以这个时候你就处于一个阻塞状态,什么叫阻塞状态啊,就意味着你现在什么都干不了,就得等着,诶老师那等到什么时候呢?诶等到三个线程对象他们有一个用完的,比方说巧了,咱们的T3线程啊,它做完了,这个工作比较简单,这两个工作比较复杂,他们时间长,这个比较简单,很快就做完了,他做完了以后,诶它就没了呀,它没了以后,这个现成对象就恢复成我们的空闲状态,所以他就变成绿色了,然后呢,我的线程池对象这个时候就会把你的这个请求干嘛呀,再提交给他,让他执行,所以这个时候呢,我们当前的紫色的工作就可以提交过来,那么它又变成了一个我们的红色,这个大家能不能明白,这就是我们线程池对象帮助我们实现的功能。我们刚才给。
08:51
大家讲的就是线程词对象的底层的基本实现原理,所以啊,很多东西你不用管,你只需要干嘛呀,提交就行了啊,你submit别的都让线程词对象帮你来做就可以了,诶老师,那我现在代码中该怎么写呢?其实告诉你更简单了,我们这里不是得到了一个叫execu service对象吗?这个对象就相当于是这个线程池对象对外提供的服务对象,所以啊,我们通过它就可以了,咱们拷贝,拷贝了以后干嘛呢?我点一下它里面就有个叫submit,叫提交。
09:24
这个里面呢,我们就可以写一个叫run ne这样的一个我们接口的一个类了,所以呢,我就直接写了,咱们之前讲过叫做new,我创建一个匿名类嘛,咱们叫run neable,诶放过来,放过来以后我这边就直接来啊,咱们来直接写,写了以后呢,我就写上它叫thread.current啊咱们的,诶,咱们叫嗯,点current,然后点get name,我把当前我执行的线程名称呢,我在这打印一下不就可以了吗?好,现在我这么写就行了,诶老师,那你现在这么写的话,不就一个工作吗?那我如果想模仿咱们刚才画图的时候多个工作怎么办?所以啊,大家看一下来,我这里写上它,我们叫做for循环,哎,我写上一个叫int I等于零,然后I小于我们的五吧,然后I加加,这样的话呢,我循环五次什么意思,我让这个线程词对象他能够什么提交五个工作,五个啊提交五份工作,那现在呢,我们就来了。
10:21
把它放进去,放进去以后大家注意了啊,我们现在里面只有三个线程,但是我提交了五份工作,那会出现什么情况呢?咱们运行一下,看一看效果来运行,运行以后看效果你就会发现。在咱们当前打印的程序当中,你会发现我的线程一它会有两次,我的线程二会有两次,我的线程三是不是只有一次呀,那么总共是不是五,总共是不是三个线程,但是它执行了五个任务啊,哎,就是这个意思,同学们能不能明白?我们的线程一它会重复使用吧,我的线程二也会重复使用吗?这个跟咱们刚才讲的不就是一回事吗?我们刚才画图的时候,这个线程三不就被重复使用了吗?当他们用完了之后,不就恢复成我们绿色的状态了吗?对不对?诶,这就是我们的一个基本思路,好了,同学们我相信啊,只要你把那个图形给它搞明白以后,难度它不大啊,诶老师啊,你说了这是一个固定的数量,那还有没有别的呀?诶咱们再来看啊,第一个咱们就说到这儿,咱们把这个东西呢,我们来咱们想想看。
11:24
还有我们的第二个,第二个是什么东西,它是根据需求啊,根据需求我们叫动态创建我们的线程,啥意思呀,如果你的线程啊,它执行工作的时候很快就执行完了,那我就可以重复使用了,那如果你的工作的花很长时间,你的线程不够怎么办?诶我就可以动态创建新的线程,所以啊,这是我们的第二种方式,那么第二种方式呢,我们来把这个呢往前放,诶我们这里写上它,咱们叫executors,诶我们写上它叫做点,点了以后,它有一个叫,哎,就这个东西叫new cash的spread pro,诶叫cash的缓存嘛,所以呢,我们放过来,放过来以后我们把这个它咱们复制一下,复制以后放过来把它注掉。
12:06
注掉以后大家会发现我这里并没有我的数量,但是呢,我这里会循环五次吧,对不对,好,我运行一下运行运行以后,诶把这个先停掉啊来停掉。停掉以后我点击运行,运行以后大家看结果,你就会发现我们这里几个线程五个,并不是三个吧,不是两个干嘛呢,是五个,也就意味着他这里面怎么了,直接根据我的任务情况,创建了五个宪政,直接快速执行就行了,诶就这个道理,老师,那如果我们有20个呢。对吧,我们假设有20个我们的线程行不行呢?来运行,运行以后运行啊,把这个线停掉,诶给它停了,停了以后我们点击右键执行,执行以后大家观察一下我们当前你会发现我们这里大家看一下实是诶有没有发现我们的现成对象其实是有重复使用的,那就说明啊,我们总共是20个任务,但是并没有20个线程,对不对,它会根据你任务的执行情况,可以重复使用线程,但是发现我的线程不够,它会创建新的线程,诶就是这样的一种情况了,好不好,同学们,这个能不能明白什么叫做动态创建呢?诶,好了,那行,这是我们的第二个啊,咱们再给大家拷贝,咱们想第三个,第三个是什么呢?第三个就叫单一的线程了,所以来我们写上它叫单一线程,什么叫做单一线程呢?其实非常简单,就是整个运行当中只有一个线程,诶老师那也不对啊,那如果只有一个线程的话,你这如果是五个任务怎么办?没办法,你只能一个一个执行了,因为它只有一个线程嘛。
13:38
啊,所以把这个拷贝,拷贝以后把这个拿过来啊,把这个去掉。哎,把这个去掉,那么把这个地我们去掉,咱们写上它,咱们叫做点,我们叫做new,诶就是它了。这个呢,就是我单一的线程了,所以我们来执行一下,咱们演示一下来运行,运行以后看结果你就会发现,我们执行当中,我们所有的线程名称它都是一,说明我们用的是一个线程,老师,那你有五个工作,现在就拿一个线程,你这个效率太低了,对不对?诶同学们,D倒是D,但是你要注意啊,我们为什么要把所有的工作都放在一个线程当中,它可能是有先后顺序的,对不对?大家能明白吗?就是我们如果想把某些工作按照某一个顺序执行的话,我们用这个单一的线程其实是可以的,没问题啊,好了,这是我们的第三个,咱们再来说我们的第四个,那我们常见总共有四个嘛,还有一个呢,我们称之为叫定时调度线程啊,来咱们这里呢,把这个给它注掉,注掉以后呢,我们把这诶我们把它注掉,注掉以后我们复制,复制以后拿过来,拿过来以后把它去掉啊,咱们写上它,咱们叫做点,诶我们来这里面有一个叫schedule的slide pro啊,这里我们也给它三。
14:51
个,然后呢,我们放到这边好了,放完了以后,诶老师这个怎么感觉跟我第一个很像呢,诶确实很像,因为当你写了三以后,咱们运行一下,咱们看结果,看结果以后大家看一下,你会发现它总共是不是也是三个线程啊,诶老师这有啥区别呢?区别就在于我们当前啊,它有个定时调度的概念,就意味着这个线程有三个,但是每个线程在什么时候执行,它可以去定义它,我们这里就不讲那么复杂了,咱们就告诉大家有这种情况就可以了啊好了,我们线程池对象咱们就简单的介绍到这里啊。
我来说两句