00:00
这个idea呢,咱们就算是整个配置完成了,那么接下来呢,我们讲这个Java的这个高级部分呢,咱们都是在这个idea的这个环境下呢去讲解了,那今天呢,咱们来讲解这个叫多线程啊,这里边儿有一个PPT直接打开。哎,多线程线程这个概念呢,大家也没有听过,所以首先呢,咱们对这个线程这个词呢,进行一个解释,那解释线程的话呢,我们就需要再去解释另外两个词啊,叫程序和进程啊,那这是我们要讲解的第一个概念啊,那咱们这一章呢,主要需要大家掌握的呢,就是关于我们在Java程序当中如何去创建多线程。嗯,那还涉及到其他一些内容,所以整个我们来看一下这一章我们主要讲的几个事情,第一个就基本的概念,程序进程和线程,这呢大家做一个了解就可以了,那么接下来呢,我们重点需要大家掌握的就是如何使用我们Java程序去创建多线程啊,这就涉及到线程的创建和使用啊,包括呢,常用的一些方法啊,这个都需要大家来掌握的,所以这呢是咱们的一个重点,哎,这是一个重点,然后第三个呢,叫线程的生命周期。
01:16
哎,从我们创建一个线程开始,就算是出生了啊,你可以想一下,咱们前面讲面向对象的时候呢,提到过一个对象的一个创建啊,相当于这个对象呢就出生了,然后对象出生,一直到你把这个对象用完。对象的用完,其实就相当于你这个,呃,对象其实也算是个变量了啊,就是你这个变量,它所定义的一对大括号,出了这一对大括号相当于你这个变量,或者说这个对象是不是自动的就算是销毁了,哎,对,这就相当于咱们一个对象的生命周期,那现在呢,咱们讲的是一个线程,那么这个线程的话呢,我们也要讲一下他的一个生命周期,就是你什么时候出生的,中间呢,会经历哪些事情啊,会出现哪些状态,最后呢,你是怎么消亡的,消亡呢有几种不同的情况,哎这样这样的一个情况,哎,这个生命周期的概念呢,是咱们首次引入,呃,以后大家学web的时候呢,我们还会讲其他的一些结构的生命周期,哎,什么时候出生的,怎么出生的是吧?哎,这个过程当中会执行哪些方法,最后呢,怎么消亡的啊,这个过程啊,还会去讲解,那么这里边呢,我们也要讲一下这个现场的生命周期,呃,需要大家呢也要清楚。
02:32
啊,需要大家也清楚,就是这块呢,不涉及到代码啊,但是会涉及到很多方法,诶这块大家也清楚,哪些方法会导致这个线程的生命周期一些状态的改变啊,这个需要大家记住啊,然后呢,在后边呢,我们要讲一个叫线程的同步,这是咱们这一章的一个重点,也是一个难点,线程的同步解决的呢,是线程的安全问题,怎么解决的,咱们到时候重点来讲它啊在后面呢,叫线程的通信,从这个名字上来看呢,一说通信感觉还是挺大的一个事儿啊。呃,其实呢,这块呢,就涉及到几个方法的使用,从这个难度上来讲,从这个重要性上来讲,都相较于这个同步呢要差一些啊,难度没有同步难,然后呢,重要性呢,也没有同步这个重要,哎,所以这块呢,主要就是几个方法,如何实现一个进程当中的多个线程之间通信,嗯,这个大家呢,就看看这个方法怎么使用好,最后一个呢,叫JDK5.0新增的线程的。
03:32
啊,创建方式实际上呢,这一个内容呢,跟咱们这个二呢,是讲的一个事儿,都涉及到线程的创建,但是咱们在刚开始讲的时候呢,呃,咱们先拿人家API里边提到的说怎么去创建来讲的这个API呢?呃,还是维护了以前的那个5.0之前的API的那些文档的说明,他没有改啊,那实际上在5.0以后呢,又多了两种线程的创建方式。
04:00
啊,在这呢,我们讲两种,在这儿呢也讲两种,那就相当于创建多线程呢,哎,算是有四种方式。嗯,大家面试的时候,如果大家被问到说我们有几种方式来创建多线程,这个你得说四种啊,你得说四种,因为在JDK5.0之后呢,又多了两种,以前呢,就是更通用的,我们是用的这两种,但是后边呢,还有两种,一共算是四种啊,那这是面试当中常问的一个问题啊,当然了,不是我们为了面试呃才去记它的啊,是你平时你要创建多线程,你也确实需要掌握的,那么另外一个常爱问的一个问题啊,面试常爱问的那一定也是重要的啊,那就是同步,同步呢解决的是线程的安全问题,那我们有几种方式解决线程的安全问题啊,那这个同步呢,其实展开来说的话呢,一个叫同步代码块,一个叫同步方法,其实你可以算成两种,那么其实解决线程安全问题的话呢,还有一种啊,就使用这个lock的方式,这个呢,也是5.0的时候新增的一个新的API啊,所以说呢,要解决线程安全问题啊,有几种方式,你可以说三种。
05:10
啊,当然你要说两种也行,嗯,你两种呢,是把这个同步方法,同步代码块算成一种啊,你要算成两种的话呢,你就说是三个啊这个咱们讲的时候呢,这三种呢都会给大家讲到这呢,属于咱们这一章里边最重要的两个内容,一个呢就是线程的创建四种方式,第二个呢,呃,解决线程安全问题,一共有三种方法,诶这呢是咱们这一章的重点,哎,大家你得明确知道重点的是什么啊好,那接下来呢,咱们就按照这个顺序呢去讲解,首先涉及到程序进程线程的概念啊,这呢是有必要让大家清楚的,好来看一下。首先先提一个概念,叫做程序,哎,大家呢,都是以后,哎,我们可以泛泛的称作就叫程序员,那如果要问一下说你是程序员,什么是程序啊,你怎么说呀,这一下给蒙蒙那个问蒙住了是吧,这个说你每天呢都在呼吸空气,问什么是空气啊,你咋解释啊啊其实有时候这些问题的话呢,在咱们看来说这些都是显而易见的,都没有必要去问去说的啊,但是当大家以后你有孩子的时候,你会发现这个事儿的话呢,还真得解释一下啊,就孩子的话呢,你会问各种各样的问题哈,就是那些,呃,这个你会感觉显而易见的一些问题,他都会问,包括我家孩子还小啊,现在才才才四个月哈,对她还不会说话是吧?呃,当然以前这个我姐家那个孩子,她是一个是一个姑娘哈,呃,几岁的时候啊,那时候问我说。
06:51
嗯,救救,我是哪来的哇,当时这个问题就是很经典的一个问题是吧,我从哪来的啊?然后呢,我说这怎么解释呢?你要说不解释吧,你打消孩子这个积极性是吧?呃,探索这个未知的这个兴趣解释吧,以前的那种,呃,上一辈都解释啊简的是吧?哎,从那个石头缝里边什么捞的什么是吧?哎,各种解释那都是比较假的是吧,孩子慢慢也都懂,所以我就想还得科学给他去解释,但是解释的又比较含蓄是吧?解释完以后呢,他直接说了一句话,我就懵了啊,哎,我就说你是从你妈肚子里边生出来的是吧?呃,大概就这样,呃,泛泛的解释一下,最后他问一句说就有人是不是我的孩子现在也在我肚子里?哎,就是很多时候你会发现很多显而易见的一些情况,我们可能用言语还很难说得清楚啊,那么这个程序啊,如果问到说说什么是程序,一个外行人一问,你还真给问住了啊,天天都在写程序,到底什么是?
07:51
程序啊,还说不出来是吧?啊那这块呢,就说诶我们呢,为完成特定的任务啊,你是想写一个聊天室,还是想干一个什么,做一个文件的下载啊等等啊,完成特定的任务,用某种语言所编写的一组指令的集合啊,你是用Java语言还是用其他语言啊编写的这些代码,代码就是指令啊结合在一起,呃,体现了它特定的一个功能或者特定的任务,哎,我们把它呢,就叫做一个程序了啊那这个程序呢,咱们通常呢,把它看作是一段静态的代码,静态的就是说它现在呢还没有啊动态起来,什么叫动态起来呢?那就像我们这个,比如我们这个任务管理器,你会看到呢,咱们这里边有相应的一些进程啊,这些进程呢,一会儿它这个数高点低点就来会动,相当于咱们把这个程序呢,给它加载到内存当中啊,这个时候呢,诶,它要去运行,还需要占用我们这个CPU的资源,这就是一个动态的过程啊,那一旦。
08:51
那我们把一个程序加载到内存当中,让它跑起来了,这时候呢,它就是一个进程了。哎,所以说这个进程和程序它两个的概念大家可以去理解,这个程序呢,它就是一段静态代码,然后进程呢,大家可以把它看作是程序的一次执行过程啊,或者理解为叫正在运行中的一个程序。
09:14
诶就这个意思,比如说呢,咱们刚才把这个idea呢,也都装好了,装完以后咱们装到哪了,我装到这个这个位置了,那么这个目录啊里边你都可以把它看成是静态的代码,那它呢,就是一个程序还没有跑起来,那我现在呢,通过点击这里边的一个图标啊,这个执行性文件,我一点击,现在呢我就把它跑起来了,这个时候你会在我们这个任务管理器里边看到这个IDEA64,诶你看它这就是一个进程,诶占用我们这个内存,你看它占的还不少呢,啊啊,它此时呢,就是一个运行起来的程序了,就是一个进程啊,那如果我把这个idea啊,现在我给它关掉,这个时候你看这个idea它就没有了,那就相当于呢,你正在运行的这个程序呢,就算是结束了,这时候以后呢,这个进程就没有了,哎,你又恢复成一个普通的一个程序了,哎就是这样,哎包括呢,像这个呃,360也一样,哎你看我360这边其实也算是这是安全卫士啊,这是一个防护的。
10:14
开着呢,我要再点击一下,你会发现它这里边又多了一个。读了哪个呢?主模块应该是它,哎,你要说不确定,你可以把它再关掉。那你看就没有了,哎,那刚才呢,我点击起来的时候呢,它相当于是把这个程序对应的这个代码呢,又加载到内存中,它此时呢,又是一个进程了,哎,就是这样一个概念,应该比较好理解啊,就是把这个进程呢,大家就看作是一个正在执行的程序就可以了,那既然你是正在执行的,占用内存资源了,它就会涉及到一个生命周期啊,从你刚开始加载开始算,那就算是出生了,加载了一直到你把它关掉,从这个进程当中清掉了,这就算是消亡了啊,这是它的一个生命周期的概念啊,程序呢是静态的,进程呢是动态的。
11:05
啊,这个意思,然后下边下边提到一个进程,说它作为资源分配的一个单位啊,系统呢,在运行的时候呢,会为每个进程分配不同的内存区域啊这个等一下咱们,呃,给大家再稍微说一下这个内存的一个情况啊,就这个进程呢啊,你会看到呢,咱们这个算是这个应用程序呢,它对应的一个这样的一个进程啊,然后这个进程里边呢,它会有具体的一些执行的一些命令啊,都是在这个进程里边呢来体现的啊,就是分配会分配相应的这个内存空间啊,然后再下一个概念呢,叫做线程。说进程可以进一步细化为线程啊,可以进一步细化为线程,是一个程序内部的一条执行路径,嗯,那若一个进程中可以同一个时间并行的执行多个线程,我们就说这个,呃,程序是支持多线程的。啊,应该比较好理解,看这个图,这是呢,咱们说一个传统的进程里边只能有一个线程,说现在呢,很多的应用程序都是支持多线程的,那就意味着呢,我们把它加载起来以后,它就是一个呃进程了啊这个进程里边呢,会有多个执行路径并行的去执行啊,那就说明这个应用程序是支持多线程,好,那还举例子,像咱们刚才这启动了一个360。
12:26
啊,我启动起来这360了,启动起来以后呢,你会看到这儿呢,就是它的这个模块占用的这个内存呢,是四九啊这有五零了啊有这样的一个大小,然后我们在这里边大家也都用过类似于360这样的一些这个安全卫士了,哎,你看我这个时候呢,可以做一个体检。啊,做个体检,然后同时呢,我这时候还可以做一个木马的查杀啊,这时候呢,我还可以做一个,呃,磁盘的一个清理,这个时候呢,你看它同时是不是三个都在执行,哎,那就相当于我现在起了三个线程,哎,你这时候你再回过来看一下我们的360占用的内存。
13:01
哎,就标上去了啊,就是这时候呢,我们这个程序呢,首先啊,我们描述的就是它呢,是一个支持多线程的啊,那你要是开的线程越多,嗯,CPU这块得得得去工作,同时呢,这个内存呢,也要占用这个空间,呃,这个内存要占用空间,你会发现它这个内存数量呢就上去了,你看CPU这块也上去了,哎就这样哈,哎这个我就不扫了,虽然说我的电脑的这个性能挺高的哈,行,我就关了,哎通过这个360大家去体会一下啊,暂停还得需要点时间啊啊哎,我们就能看到这个360呢,它是支持多线程的啊,就这个概念,好接着回过来再说这个线程啊,你你要是一句话来描述它呢,你要说这句话是一个程序内部的一条执行路径,这就叫一个线程。哎,就像咱们之前写代码的时候,这个咱们把这个idea让他也先跑起来啊。
14:01
那这个需要CL的时候,我们顺便也先打开一下。嗯,就是咱们原来呢,都是写的一个没方法。嗯,那其实一个没方法,我们点这个右键,诶让他去做一个,这个果真起的慢一些啊,比我们这个一起的要慢一些,嗯,这个我们在这里边是咱们写的这个项目了啊,诶我这点右键有一个叫run as Java application,它就相当于从这个main方法进来开始去执行这两行代码了,实际上呢,这个main方法它对应的呢,就是一个线程。哎,就是你从这进来开始这块呢,开始执行,这就是一条执行路径。哎,就这个意思啊,好,那么下边就提到了,说线程呢,作为调度和执行的单位,每个线程呢都独立的啊,有独立的这个运行站和程序计数器啊,线程切换的开销比较小,呃,下边呢又提到说,呃,咱们这块呢,等一下来看下这个内存的结构啊,先接着往下来说这个一个进程,它里边呢可能会有多个线程,那么这多个线程的话呢,它会共享这个进程的一些内存资源。
15:09
啊,那都可以共享哪些啊,那这块呢,咱们来说一下这个内存的结构,这个内存结构咱们要说的话呢,那咱们就拿一下这个完整的这个GVM中的这个内存的一个结构来说明,咱们这个课件呢,这个第三部分啊,这块呢,涉及到这个GVM了啊简单的给大家来说一下啊这呢是咱们比较这个规范的官方提供的一个,呃,内存的一个结构啊,这个先是需要类的加载器,把我们这个点class文件呢加载进来,这块呢,关于加载的事儿,咱们讲到反射的时候呢再说啊呃,大家呢,目前这块呢,先就快速的过过掉啊,然后呢,加载完以后,我们这个呃数据呢,或者我们这个类呢,就加载到内存当中了,那内存里边呢,有这样的一些结构啊,有方法去堆虚拟基站,程序计数器,本地方法站啊,这是内存区域里边核心的这样的几个结构,那么虚拟基站就是咱们讲面向对象的时候呢,提到的那个站。
16:09
啊,本地方法站只涉及到native的一些方法啊的一些站结构啊,这个呢,咱们就目前就不提了,成为计数器这个呢,和我们这个虚拟驿站它俩。注意啊,它俩每一个线程有一份儿。如果我们这是一个,我举个例子啊,这是一个进程,这个进程里边我们如果有两个线程,那就意味着这两个线程各自有一套,占有一套程序计数器啊,各自有一套的,然后呢,还有一个叫方法区和堆,呃,咱们前面也稍微提到过啊,像static呢,呃,静态的这个结构我们在方法区了,然后呢,我们new的一个对象啊,都是在这个对空间中的啊,对空间里边还有你这个对象的一些实例变量啊,这都在堆的,然后方法区和我们这个堆呢。哎,不是一个线程一份的,是一个进程一份啊,一个进程一份,而我们这个进程里边呢,有多个线程,那是不是就意味着我们这多个线程要共享方法去核对呀,哎,对的啊,就这两个呢,是一个线程一份,然后这块呢,是一个进程一份,然后多个线程共享啊,一个进程当中的方法区和对啊,比如我们堆里边提供了一个实例变量,是不是就意味着我们两个线程都有机会来进行修改啊。
17:31
啊对的,后边呢,咱们讲到这个GM的时候呢,还会提到这个GM一些调优啊,调优呢,其实主要针对的就是我们这个共享的这个区域呢,进行调优了,因为你自己这块呢,也没啥可调的了,其实啊,就是针对于共享的数据,我们怎么去让它进行优化啊,是这个问题啊成这块呢,就给大家说一下这个问题,那么还回过来啊,这块呢,就能说明这个事儿了,就是我们系统分配的时候呢,给每个进程分配了不同的内存区域啊,就是每个进程会有一个独立的方法区和对空间啊,然后呢,这个线程的话呢,它有独立的站和独立的程序计数器,每个线程一份啊,然后呢,一个进程当中呢,多个线程你是可以共享咱们进程当中的这个堆和方法区的啊,那么我们使得因为你能够共享同一个进程中的这个和方法区了,其实我们这个在这个进程之间通信呢,会更加的方便和高效,因为你本身是不是就能够看到这里边的这些数据了,哎,所以咱们呢。
18:32
通信是什么意思?通信就是说,比如说诶,我这个线程来操作,操作这里边儿的某一个数据,然后我操作到一定程度的时候呢,我就停了,我停了之后你你接着来操作,你操作到一定程度之后,我再来操作,这就算成一个通信了啊,因为呢,天然的我们这多个线程就可以来共享一个进程当中的这个堆空间,所以说呢,呃,实现多个线程之间的通信是比较方便的,因为本身你是共享的。啊,就跟说呃,大家以后租一个房子,嗯,租一个房子的一间,然后你旁边还有这个室友,你们本身就共享这个厨房和厕所啊,那你俩都去厨房厕所,都去厨房的时候吧,是吧?哎,你们是可以交流的是吧?哎就是相当于这个更方便一些,你跟另外一套房子的一个人交流,其实是不方便的了,哎,因为天然这个厨房你们就共享,哎当你都进来的时候,大家就可以聊天是吧。
19:23
啊哎,这是说的这个事儿啊,嗯,然后呢,这里边抛出来一个问题,大家看我们多个线程,既然呢是可以操作共享的数据,那么这个时候呢,是到底你操作呀,还是我操作呀,还是说呢,我正在操作,这个时候呢,你又也来操作了,这个时候是不是就会出现一些问题啊哎,那我们把这个问题呢,就称作一些安全的隐患,那么这个安全隐患呢,也确实需要我们来解决,这就是我们这个节要说的线上的同步啊,就是来解决这个,诶共享这个数据,你也来操作,我也来操作,那咱俩到底是怎么操作。啊,我还没操作完了这块,你又来操作这后不就乱套了吗?哎,我们就哎讲这个叫同步来解决这个线程的安全问题啊行,那通过刚才这样个说明,大家把这三个概念呢,哎有个更清晰的理解啊。
我来说两句