00:00
OK,那么关于线程的话呢,咱们就讲完了啊,那么咱们针对线程这一章呢,做一个复习,诶首先呢,打开咱们对应的这个课件,诶,找到这个零三线程,诶打开。OK,那首先呢,我们回忆一下,我们这一章呢,主要讲了几个问题啊,那第一个的话呢,我们提到了几个概念。啊,几个概念涉及到比如说程序进程线程并行并发是吧,类似的这个概念啊,这是第一个问题,然后第二个问题的话呢,我们提到了叫诶如何呢去创建多线程这儿呢,也是咱们这一章的一个重点内容啊。如何创建多线程,OK,然后呢,第三个问题,哎,多线程创建好以后,这里边儿我们发现呢,多少都跟thread这个类呢是相关的,所以下个问题呢,我们提到了这个,诶thread类的常用方法。啊,这是一个事儿,然后另外呢,我们也提到了,叫现成的生命周期。好,这呢是我们说的这个点,然后接着第四个点,这儿呢,我们就回归到说呢,创建了多个线程,如果呢,他们要有共享数据的话呢,就会出现线程的安全问题,那下个问题就是诶如何解决线程安全问题,这呢也是我们这章的一个重点,也是一个难点。
01:13
啊,这呢,就使用这个同步机制了,OK,然后呢,由这个线程的同步机制出发,我们又引发了几个相关的问题啊,诶同步。机制啊相关的这个问题。那OK,这呢,就我们今天早上讲的,比如说如何解决这个懒汉制的现场效问题呀,词索的问题呀,包括这个lock索的呀,哎,这个我们都算成是第五个这个知识点里边的。好,然后这个完了以后呢,我们接着又讲了个叫线程的通信。行,这呢我们就说到这儿,然后最后呢,我们讲的另外的两种创建线程的方式,咱们可以呢,就都归到这个里边了,这呢就是咱们这一章呢讲的几个问题,好首先呢,来看第一个点分那几个概念啊,这几个概念呢,我们主要呢,就涉及到了这样的几个哈,诶首先呢,就涉及到这个程序进程线程这儿呢,在相关的比试当中啊,有时候还确实会问到的这个问题啊,所以这块呢,大家能够用自己的语言呢,给他答出来呢就可以了。
02:11
呃,用某种语言编写的一组指令的集合啊,或者你这块呢,你说不明白呢,你可以就说后边这个啊,就是咱们装一个软件,比我装到C盘啦,D盘了,相关的文件目录下了,那相关你文件目录下的那个代码啊,在磁盘中存储的,它其实就叫做程序了。然后呢,进程呢,就是这个程序呢,一次运行的过程,那运行当中的程序呢,其实就是一个进程啊,需要呢,我们占用相关的内存资源啊,使用CPU进行运算的,所以它是一个动态的过程。然后线程的话呢,是这个进程的进一步的细分啊,一个进程里边呢,是可以有一个或多个线程的,一个线程就是一条执行路径啊,也非常的清晰啊,然后呢,这边两句话呢,你要是加上的话呢,会显得level呢会更高一些啊,这头呢,看到是咱们操作系统调度和分配资源的最小单位,这个大家理解呢,就从我们这个任务管理器这块呢,看这个进程就可以了。
03:05
这都是属于叫基本单位了。好,然后呢,下边这个线上呢,叫做CPU调度和执行的最小单位,CPU呢,我们快速的去切换任务,这个所谓的任务呢,其实就是具体的这个执行路径了,所以这块呢,我们最小的单位呢,其实是这个县城,包括呢,我们看这个内存结构划分的时候呢,咱们说呢,站这个站的话呢,也提到了,就是每一个。呃,线程它对应的是一个站啊,一个站的话呢,我们里边呢,就可以放相应的这个方法啊,以战争的方式这块往这怼过来。啊,这样的形式啊,然后呢,在这个内存结构当中,我们说主要的一个结构呢,一个叫做栈,一个呢叫做堆。哎,在这里边儿呢,有一句话啊,咱们也就这么一说,大家一听就行,叫做什么呀,叫站管运行,堆管存储。哎,你看我这样一说,能不能理解所谓的站管运行呢?就是咱们在Java里边呢,咱们不都是通过一个一个的方法的调用,体现了你这个运行的一个过程吗。
04:00
那么每一个方法的调用呢,其实都对应的是一个战帧,它呢要入站,所以呢站呢主要来负责管运行的,而在整个这个过程当中呢,你会涉及到一些对象的创建啊,那么对象的创建呀,数组的创建呀,等等这些数据呢,我们说都是存放在堆里边的。哎,所以呢,叫站管运行,堆管存储,那这个运行的时候呢,最小的一个调度单位呢,就是这个叫这个这个线程了啊,每个线程有一个站,OK。啊,这呢是我们说的一组概念啊,然后呢,另外呢,呃,这块我们还提到了这个,呃,县城的这个调度策略是吧,分时调度这个呢,就是平均分配时间,让各个县城执行了,抢占市呢,就是高优先级的抢占低优先级的啊这个呢属于一个补充的内容啊,也不是特别难啊,应该一说呢,大家也能去理解这个事儿啊。哎,这个我们把它呢也稍微的粘过来吧,这呢做一个了解就行啊,倒是笔试面试的时候呢,倒没有问这个事儿的。啊,这个粘过来,然后呢,关于这个并行与并发呀,咱们以后的话呢,还会去讲这个问题。
05:02
啊,这个大家呢,不用在这块呢去深究OK啊以后呢,我们提到呢,高并发的时候呢,我们再还会说这个并发的问题,单核CPU多核CPU啊这呢也做一个了解就行。行这呢,我就简单的就哎放到这儿了啊,具体呢,大家可以看一下我们这个课件。这呢我们就过掉了,这块呢,这个问题大家稍微关注一下,笔试呢可能会考,然后下边一个呢,涉及到如何创建多线程,自然而然的话呢,就会问有几种方式。对这块我们要说的话呢,应该算有四种方式是吧,第一种呢,我们说的呃,叫方式一啊,叫做继承thread类的方式。OK啊,然后方式二呢。哎,实现renoable这个接口。啊,你也可以呢,念念作呢,叫run able是吧,也可以,然后方式三。实现叫或者叫call是吧,这样的一个接口。84。对,使用线程池的方式。哎,先生池,OK好,这呢一共呢,就相当于我们讲的这四种方式啊,这个第三种方式和第四种方式呢,是是在我们这个JDK5.0的时候呢,新增的。
06:09
哎,但是你看我们这块新增完以后呢,在这个API层面呢,你却看不出来哈,这个API的话呢,它这还是写的,我们现在都已经用的是17的API了,现在在这个位置我们输入这个thread的时候。啊,第一个位置进来,他这块呢,还是写的是吧,啊有两种方式来创建。啊,其实呢,你发现这种情况呢,不光是我们这个里边啊,在很多的位置呢,其实你都会看到它,其实这里边的API呢,说明文档好多呢,都没有及时的去做这种更新啊,诶说的还是比较传统的这种方式了,诶当然我们这块呢,后续呢,有一些更新的地儿呢,都会加上的啊。所以呢,我们习惯上一提到啊,面试里边如果问到说几种方式,我们还是要提到有四种方式的,OK。然后呢,这些方式里边呢,咱们大家需要重点关注的呢,还是属于第一种和第二种啊,这是属于传统的比较经典的方式。啊OK,好,那么相应的这个方式的这个对比啊,等等的这个呢,也是咱们这个的重点啊。
07:05
哎,比如说提到这个继承和实现是吧,诶我们讲到说这个实现呢,比这个继承呢要好一些。啊,这个咱们提到了第一个呢,呃,解决了单集成的局限性啊,你集成二类了,你就不能集成别的类了,而实现呢,就更灵活一些。啊,而且呢,我们这个实现的这个接口的实现类的对象呢,我们可以把它放在多个啊线程的这个诶构造器当中啊,比如我们这里边写的哈,我把当前这个类的对象啊,我只造一个,然后放到这个TH的这个构造器里边了啊,然后我再放一个,此时的话呢,我们这个P呢,天然的它就相当一个共享数据。对,所以说对于有共享数据的,呃,多个线程来讲呢,我们使用实现的方式呢,就更方便一些啊,天然它就有共享数据。OK啊,那那其实呢,共享的数据就是我们这个类的对象了,所以呢,这个对象呃,这个数据就是它这里边儿的属性,然后具体的操作呢,就是这里边儿这个代码逻辑啊,其实呢,也算是一种分离,只不过这个分离呢,似乎呢,大家体现的就不是那么明显了,是吧,我们在这写好处的时候呢,这不也提到这样一个事儿啊。
08:06
好,呃,这呢我就不用去细展开来说了,这呢是咱们这章的重点,那这两种方式呢,大家先不用去。自己呢,非得独自的去实现,先还不用啊,以后的话呢,涉及到GC的时候呢,再重点的讲这两种方式OK。好,下面提到呢类的这个常用方法,现成的生命周期啊,那常用方法这块呢,其实我们还提到这个构造器的问题了。嗯,这块呢,大家也就熟悉一下就行。啊,你看找到我们这块扩大器呢,就这几个咱们常用的啊,然后方法这块呢,是有这样的一波啊,所以呢,我就简单的把这两个呢,CTRLC拿过来,这块呢就熟悉就行啊。这个要求呢,就比较低了啊,要熟悉是吧。常用的这个构造契合方法啊就可以了。那我们呢,提到了有这样一些方法啊,那这些方法的调用呢,会导致我们这个线程的状态呢,会发生变化,那这个所谓的状态就构成了我们线程的生命周期了。
09:03
啊,在这个讲生命周期之前呢,我们还提到了一个这块的关于县城的这个优先级的问题,啊,这个咱们也把它呢拿过来。那我也就放到这儿了啊诶油先机这块呢,涉及到也是对应的有方法,还有三个全益常量啊好,下边呢,我们提这个叫线程的生命周期。OK,这个生命周期的话呢,有时候在这个笔试和面试当中啊,也会问到啊,那如果问到大家的时候呢,那当然了,我们推荐大家你说的话呢,还是要说5.0之后的是吧。哎,那5.20之前呢,咱们这块呢,给大家画了个图。嗯,这个呢,我们找一下啊,就在这儿呢,这个5.0之前,这个呢,其实是容易大家去理解的。诶,所以这块我们先把这个图呢拿过来。嗯,在这儿啊,这个是JDK5.0啊之前的啊,这个场景好,然后呢,JDK啊5.0之后。
10:00
这个时候呢,我们发现呢,在这个read这个类中。啊,累。中啊,定义了一个内部类是吧,这个内部类呢,还是一个。枚举类哈,叫做state,这个state呢,就是我们说的这个生命周期了啊,CTRLN一下,咱们来一个thread。找到我们这个位置,诶这个咱们看哪个都行哈,看17的,诶17这里边儿呢,在CTRL f12找一下这个state。哎,这是一个霉菌类啊,这里边呢,它就罗列出来了,我们这个线上的几种状态,哎,CTRLC一下。哎,这个呢,我就把它呢粘过来啊。里边呢,这个注释呢,咱们就可以删一删稍微的啊。我就把它去一去了。OK啊,这呢,就我们说这个线上的几种状态。啊,那么在这里边的话呢,我们就能看得比较清楚啊,首先呢,这个叫新建啊,这叫可运行,这叫阻塞啊,这个叫等待,哎,有时间限制的等待啊,这个呢叫死亡,哎这样的几种状态OK,好,然后呢,对应的呢,我们说哪些方法的执行会导致这个状态呢,出现切换呢?哎,这个我们在课件里边呢有写。
11:22
然后我们上面这个生命周期。嗯,找在。周期在这呢。然后这块的话呢,呃,如果呢,如果要记住一个图的话呢,那这块就涉及到就是这个图了。哎,这么着啊,哎,我把他俩盯过来。哎,这呢,我就放到这儿了,行,这个图里边的话呢,我们也比较清楚的知道它这样的这种状态,以及呢,哪些相关的方法呢,会导致状态呢,出现这种切换,哎,这里边呢,还标识了一些我们没有见过的一些方法,这个呢在以后的GC当中我们再去设计,所以说现在线程这块呢,我们在基础阶段也就是适可而止。
12:01
啊,后续呢,还有很多高级的内容需要我们去学习的啊,这个我们就不再展开来讲了,诶目前呢,涉及到的一些方法呢,哪些呢是叫time waiting,哪些叫block,哪些叫waiting啊其实这里边大家找咱们提到的呢,也都说过了啊,所以这块就不多说了。啊,这是我们说的这个生命周期,诶,可能在笔试当中会被问到的下面一个问题,这呢是咱们这一章的一个重点,也是一个难点。OK啊,其实重点也是个难点,呃,怎么体现呢?说如何解决线程的安全问题,首先呢,你得要清楚说什么是线程的安全问题。哎,这个怎么说呀。对,就是多个县城。哎,操作共享数据是吧。哎,就有可能出现安全问题。OK啊,这个呢,就我们提到的这样的一个场景,那这里边儿这个操作呀,一般呢,咱们其实都会涉及到对这个数据呢,进行一个修改的行为。
13:05
对,如果呢,你要只是说去读一下这个数据,那没关系是吧,你既然不会对这个数据产生影响,大家都是读,那就没问题啊,大你去读,你也去读,你也去读,大家呢,直接呢并行的执行其实就可以是吧,就没关系啊,关键呢,就是说怕其中的一个线程去修改,这个修改的时候呢,其他的线程过来,虽然假设也是个读的行为啊,这个是改,这个叫读。那你说我是,呃,你你你是这个写的过程当中让不让读啊,啊这块我们就需要考虑这个问题了啊,这个呢,其实就有可能会有这种安全问题,所以这块这个操作呢,主要涉及到就是有血的行为啊。好。那么既然有这个安全问题了,我们下边就要考虑如何呢去处理这个安全问题啊。现成的安全问题,那这呢就涉及到了有几种方式。这个怎么说呢?有几种方式啊?呃,说两种也行,说三种呢也可以是吧?诶如果呢,你要说两种的话呢,你可以一个呢说呢叫同步机制,这个同步机制呢,其实细分呢,又分成两种。
14:08
一个呢叫同步。对代码块第二呢叫同步方法。啊,这呢,其实都理解成叫同步机制的,然后另外一个呢,可以理解成是JDK。对。CDK5.0新增的是吧。那这样一种方式,就是我们这个lock这个锁啊,就是使用这个lock接口机器实现类。诶来去实现啊,然后咱们这里边儿呢,就给大家演示了一个啊叫rein tradelo叫可重入锁来关于它的一个使用。所以这块呢,要大方向来讲呢,其实算两种方式,你要说三种也行,那就是一种两种三种。啊,这个注意一下。好,那么具体呢,大家在使用的时候呢,咱们这块呢,先暂且呢,也是做一个了解后续GC呢再说,然后在我们这个同步代码块同步方法这块呢,咱们讲的时候呢,因为上面呢讲了两种创建方式啊,一个呢叫继承,一个叫实现,这块呢又提到了两种解决的方案,同步代码块同步方法,所以呢一搭配啊,这两种同步,这是一个继承一个实现,一搭配的话呢,就是。
15:13
四种情况咱们都给大家呢去讲解了,那么需要呢落地啊关注的点,把这里边这个重点问题呢稍微提一下,我们这儿呢写了两句话啊,第一句话,在实现reno这种接口的方式当中,同步然器。那这块呢,大家可以考虑使用这。而在这个技能的方式当中呢,要慎用这次,所以我没说不让用啊。啊叫慎用,你包括呢,我们从这个客户的练习题的角度来看,比如说这呢,我们写的这个,呃,两个人呢,去往这个账户里边存三次钱这个事儿,这呢我们用的就是继承的方式,然后呢,我们这儿呢,这不也相当于用的算式叫Z吗?所以说能不能用呢,这个不要呢,去妄自下这个结论,呃,你只需要关注一个点,这个同步监视器呢,我们说呢,必须保证是同一个。啊,具体能不能用,这次呢,你去细看,只不过说在这儿呢,叫慎用。
16:04
OK,这个呢,是我们说的一句话。啊,咱们把它呢,这个拿过来啊,我就放到这儿啊,这个我再这样吧。这呢是一组我们要注意的点,然后另外一个呢,就是我们提到了,对于同步方法来讲,由于呢,它的这个同步监视器呢,是默认的了,所以我们需要呢,清楚默认的到底是什么样的一个场景啊,就我们这里边写的这个事儿,非静态的呢,默认的就是Z,静态的话呢,就是类本身。啊,那这个类本身呢,通常都不会有问题了,因为这个类呢,诶都是加载一次的,所以是唯一的,关键呢,就是非静态的同步方法呢,它是Z的,这个你要考虑清楚这个Z呢是不是唯一的,如果要不唯一,那你这个非静态的如果做成同步方法呢,这个仍然不能保证这个线程的安全性啊呃,这个也是我们要考虑的一个问题。这儿呢,我们就留下来的这两个,诶。注意点啊行,这呢是我们提到的关于这个同步机制里边的这个事儿,做成我们这一章的一个重点是难点,实际上呢,从代码角度来看呢,并不是太复杂,咱们只是在继承或者实现的基础之上呢,只是加了一个这个啊S。
17:14
啊,要么呢是一个代码块的形式,要么呢是一个方法的一个形式,诶但是呢,这块呢,你加了以后呢,到底能不能解决安全问题啊,这个呢是一个技术活。需要我们重点来考虑的啊。所以呢,回过来呢,再要说一句话呢,这里边儿大家要重点关注的点呢,其实就是说呃,两个问题。啊,这会大家说一下啊,这个重点关注。啊,两个事儿啊。呃,这两个事儿呢,要搞定了,基本上就还好了,第一个呢,就是共享数据。诶,共享数据及操作共享数据的代码。哎,代码啊,这个首先明确共享数据是谁,然后操作共享数据的代码呢,我们需要呢,用同步方法,或者同步代码块呢,给它包起来,这块呢,注意一个点就是既不能包多了,也不能包少了。
18:07
包少了的话呢,可能就不对是吧,比如说这块呢,我们有啊,假设这五行代码呢,是操作共享数据的代码,你呢,只把。这三行包住了,那么就意味着在两个线程过来以后啊,在这个过程当中是一个线程的,那出来以后呢,万一在这又停了,然后你这个线你这出来都释放了啊,我们减起来,然后这个线程也过来,这不是仍然会有线程安全问题。所以包少了不行啊,那包多了呢。包多的话呢,肯定安全是吧。对,但是剥脱以后呢。对,你毕竟在这个过程当中是一个单线的问题嘛,这个性能就没有体现出来了。诶,所以这块呢,都是要要重点考虑的这个点啊这个事儿,另外呢,就是我们说的这个同步监视器是吧。它呢倒是对类型没有要求,关键呢就是要保证唯一性是吧。诶,这个呢是我们重点要考虑的,那么这个保证唯一性呢,放到我们这个lock这块呢,也是一样,它呢没有这个土木加湿器了。
19:04
它呢有的就是这个接口的实现类的对象,所以这块呢,提到针对于他来讲的话呢,就是要保证多个线程共用同一个,是不是lock的实力啊。所以这块我们在使用这个re log的时候呢,咱们用了一个that这个修饰是吧,就保证它是唯一的啊这样一个点。行,那这儿呢,我们就诶不重点呢,展开来说它了哈,从一个面试题的角度来讲呢,就是它呢,也是一种方式啊。这就过了,然后下边呢,相关的问题啊,那我们把这个lock呢写到上边了,那这里边儿呢,就涉及到有两个了,第一个呢,叫做懒汉式的县城安全。啊的这个写法啊,这个大家要关注一下啊,在笔试题当中有时候会出现哈。嗯,这是一个点,然后另外呢,就是我们说的这个思索问题啊。这个呢,是我们同步机制会带来的一个问题啊,叫做这个思索。
20:00
那我们能做的事儿呢,就是尽量的去避免思索是吧,那就涉及到了,诶思索呢产生的条件。啊及啊规避的这个方式。这个咱们在这个课件里边呢,有写产生条件有四个,呃,针对这四个条件呢,我们如何呢去规避啊,这块呢有写啊,所以我就不在这儿去说了,一会儿下边儿呢,企业之地当中还有。然后下面一个呢,叫线程的通信,哎通信呢这块呢,就实现了线程,比如说我执行一会儿我wait了是吧,我交给你执行啊,你执行一会儿你喂置一下,你再唤醒我交给我执行,所以这块就体现了这种叫通信的一个概念了。OK,那这个通信的话呢,注意咱们呢,在这里边儿呢,没有去针对于lock啊讲解它相关的通信。这个还得放到GC里讲了啊,咱们这边的通信呢,都是基于一个大前提。啊,是在这个同步机制下是吧。哎,然后呢,考虑叫呃,线程间的这个通信OK啊,那就意味着我们接下来讲的这几个方法啊,涉及到一个叫V的。
21:06
对啊,Ninety five。哎,这个在哎,Notify oh啊这三个方法的话呢,都需要使用在。在这个同步代码块或者是同步方法中。OK啊,这呢,我们的这个对应的这个注意点了啊,而且呢,我们说呢,三个方法的调用者必须是谁啊。对,同步加湿器。诶,这个土木监视器是谁啊谁呢?诶发起对它的一个调用啊,注意一下。好,那么有没有同学会说,诶,那我们这个同步加然器是不是可以用当前类本身去。表示是吧。就我们所说的当。是不是也也可以呢,作为同步加湿器是吧。哎,那你说诶,那是不是这三个方法应该声明成是静态的呢。怎么说呀?诶,首先的话呢,在我们这里边儿,这仨方网还真不是静态的啊。
22:03
但是呢,那你看那样的话,我们这个泪怎么去掉啊。你看我这个问题有道理不?啊。嗯,对哈对,就不要被我这个问题呢给蒙住了啊,那这个的话呢,咱们也没有说过同步监视器能够用泪啊。哎,咱们一直也没说这事就是类啊,这不说的都是它是对象嘛,是吧,对这不是类哈,不要把它看成类,它呢,其实是我们这个大的class的这个实力是吧。这个是大写的C哈,这个我们到反射的时候会说它呢还是一个对象啊,所以说这个方法呢,它就是非静态的。啊,千万不要一看到这有个泪点,Class说,诶,那这是不是应该用泪也可能掉了又又陷进去了,这是对象啊,注意。所以是非静态的啊。好,然后呢,这个线程通讯这块呢,大家不用把它当成是一个重点啊,诶这块呢,你又主要还是关注于咱们这一章呢,呃,有同学呢,可能觉得学起来呢,稍微有点痛苦是吧,尤其是在处理这种限制安全问题的时候啊,通信呢,我们写了一个生产者消费者啊吧啊又不太好写,那其实呢,这一章呢,你就记住俩事儿,第一个呢,怎么创建多线程,这里边呢,你就知道有四种方式,重点呢,你把前两种写一写,然后第二呢,就是同步机制咱们去解决啊,我们重点呢讲的是这个S的。
23:25
你把这个形态的这种方式呢,你给他。诶再去知道怎么去处理,其实呢,核心问题就已经拿下了。啊,再者呢,你说再关注,那就是把几个常见的笔试面试题给大家拿下,一下就搞定了啊OK。诶,这块呢,通信啊,不用太过于关注啊,你要非要关注这块怎么着呢,有一个笔试题是吧,就是wait和sleep的一个区别嘛。啊,这呢是一个高频的笔试题啊。哎,Wait和这个sleep啊,因为呢,通过问这个问题啊,基本上呢,也就能够把咱们这一章里边相关的一些知识点呢,都能带出来,你比如说呢,会造成阻塞呀。
24:03
是吧,这就涉及到你现成生命周期的问题了,然后呢,诶一个能在同步代码块中,一个呢必须在同步代码块中用,一个呢,没有限制,诶同步代码块这不涉及到同步机制啊,就是安全问题了,诶怎么去解决这个阻塞的这个场景,诶自动的这个到时间了它就解了啊,一个呢,还得需要去notify啊,这就涉及到了我们这个通信的问题了,所以这两个呢,呃,你答得好,其实呢,也就基本上知道你这一章呢相关的同步机制啊。创建方式啊是吧,这个相关的一些这个生命周期啊,哎,你是清楚的OK啊。好,这呢就过掉了啊,大家不用重点关注它两个事儿,如何创建,如何解决安全问题,这是核心,好下面来看一下这个真题,第一个什么是线程。什么现场啊?刚才刚说过是吧。呃,两个点哈,第一个的话呢,就是我们,呃,进程当中的一条执行路径,实际上是一个线程。是吧,这个呢是一条执行路径,然后呢,另外的话,我们提到它是CPU。
25:05
在执行的时候的一个最小单位了是吧。哎,这个就略了啊,这个咱们上面都写着这个答案的。诶,进程和线程啊,有什么区别。啊,这样说吧,进程呢,它其实对应的是一个运行中的程序是吧。对应一个啊,运行中的这个程序,大家呢,其实用的手机呃,你每一个APP你给他点一下启动起来,其实这块呢,自然而然的,它至少就有这样一个进程,至少有一个啊,他有的可能还会有一些后台的独立开辟的一些进程啊。就是运行中的程序啊,那么这个线程呢,那就是呃,运行中的。啊,进程。进程的这个一条或者多条执行路径是吧。啊,你比如我们提到了这呢,你拿这个手机,然后这块儿呢,就是相应的这个新闻的信息了,然后你往上滑,整个呢,这块儿可以理解成就是一个进程,然后这块呢,每一个图片呢,你用独立的一个线程呢,去下载一个线程,这不就是一个。
26:10
执行路径吧。OK啊。好,你看这块问的还挺多的哈。好,下边多线程的使用场景,诶这个怎么说。哎,这个咱们讲的时候呢,似乎没有提这个事儿是吧,这块大家可以呢,举一些例子啊,你比如我们刚才举到的说这个,哎,咱们具体这个像呃,手机这个APP,呃,这个具体的应用的图片的下载。这块呢,就是每一个图片呢,我们可以使用一个线程来去下载,而且这块使用的是线程池啊。嗯,还有吗?啊,一条这个下载的话呢,大家可以再考虑,比如说像我们说的这个迅雷。迅雷的这个下载类似的这种下载软件,你发现了它下载速度非常快是吧。它怎么就快了呢,比如这有一个G的文件,它呢可以考虑把这一个G的文件呢,首先呢,在本地呢,我先给你开辟出来一个G的空间。
27:00
然后呢,诶我这儿呢,可以如果要使用四个线程下载的话呢,我先定位这呢是开头这个呢是第二个线程,第三个第四个线程,这几个线程呢,同时开始去下载。哎,自然而然的,它这个速度呢,就会更快一些啊,这类似的这种下载的行为。嗯,还有什么呢?嗯,还有呢,比如说啊,以后呢,我们会接入到这个服务器哈,像这个汤派的这个服务器。诶,服务器上的话呢,我们对应的有这个叫外部应用。啊,外部应用就相当于我们一个应用程序了,那么客户端的话呢,可能会有多个啊,比如说几百个客户呢,发送这个发起呢,对这个外部应用的一个请求,那么这个他们服务器呢,针对于每个请求呢,会开辟相应的这种线程呢来进行处理啊。哎,多个。诶,客户端啊,发起这个请求。那么他KD呢,哎,就是针对多个请求。诶相当于呢,就是开辟。
28:00
诶多个县城来处理OK啊行,其实呢,这块挺多的啊,包括呢,我们有相关的,大家你可能看到有一些比如说你注册一些网站了,然后呢,上面放你邮箱了,然后时不时的会收到一些垃圾短信是吧。这个垃圾短信你能收到,别人可能也能收到啊,往往这时候发的时候呢,可能他都是成批的一发发100万封。是吧,这种邮件出来了,然后这时候他在发的时候呢,其实也是使用这种多线程的方式啊。啊,其实这种场景呢,非常多啊,这个你就举个例子就行了。然后呢,我们接着再看说如何实现多线程。啊,你也可以理解成呢,实现多线程有几种方式。这个咱们说有四种了是吧。啊,这个我就写上啊,四种方式。哎,这块呢,有类似的问题。啊,这个具体细节呢,就不用多说了啊。好,下边一个说二类的方法和run方法有什么区别?对,区别还是比较大的是吧。对大化呢,咱们说有两个作用啊,第一个呢,叫。
29:00
开启线程是吧,第二个呢叫。调用现成的。哎,软方法。所以说你要说调转呢,其实只相当于start里边的一个事儿。哎,掉star的话呢,可能会启动一个线程的,你要直接掉转呢,相当于线程根本没起。嗯,那就是还在你原有的线程当中,只是相当于一个对象调方法是吧。对啊,下边一个,哎,这个不用多说了,就start是吧,还是某度的是吧。好,下一个说Java当中的randomable和able有什么不同?咱们特意写了是吧。啊,在我们的这个位置啊,哎,下边啊。在这儿。啊,有个菱形的变量哈,那个叫泛形啊,叫泛型,哎,你要叫的话呢,别叫菱形叫什么呀。啊,叫diamond operator。翻译过来呢,叫钻石操作服。对,你叫别叫灵醒,叫钻石是吧。
30:00
啊。好,这个呢,就是我们说的它俩的区别,这个区别的话呢,主要我们说的还是Co的优点多一点啊。当然呢,也有缺点是吧,这块我就放到这儿了。下边什么是线程池?为什么使用它?啊,这个呢,首先咱们没有重点重点展开讲,就我这里边放的这个面试期啊,就是从诶真的就是大家呢,毕业以后呢,就是面试题当中呢,就一点点给他缩了回来的,然后一点点给他再去过滤是吧,然后呢,看看哪些适合放到哪些章节,其实花的时间还是挺多的啊呃,然后这里边的话呢,他这个问题啊,不一定是局限于我们基础阶段啊,其实有些点的话,我们只是在这儿提了,其实呢,诶后边呢,结合着GC再去讲会更合适一些。行,那我们目前呢,能够解释的点呢,其实就提到它的一个好处,具体关于它的使用,包括具体的一些方法呀,参数啊,以后再说。啊,以后再说行,我们也就提到这就到头了啊。下边提到sleep和的一个区别。这俩还问了一下哈。这你就从生命周期的角度考虑是吧。
31:02
哎,这个的话呢,会使得这个线程进入。啊,一旦调用是吧。就。进入咱就阻塞了,这个呢,是从咱们传统的角度来说呢,叫阻塞,实际上呢,我们要从生命周期的角度来说呢,叫。是。哎,有等待。时间的这个。哎,不是有时间的这个等待是吧。Time waiting。我还是直接。抄一下吧。咱们刚才在这就这个。就进入这种状态了。Time waiting这个状态。好,那你这个业务在哪。对,他只会释放CPU的职权,它其实还在那个renoable里边呢,是吧。啊,这个呢,是释放C的行权是吧,还是呢,处在这个。
32:04
在这样的一个状态。就这啊,就是这个呢,是咱们从这个5.0之后的这个生命周期来看呢,啊,因为这块看这不还在这里边呢吗。OK啊。好,这个呢,就过了,这个一般问的比较少,其实啊。啊,这下一个说线程创建中的方法属性如何,这个咱就略了啊,就是thread里边那些方法。哎,现在的生命周期啊,也讲过了。哎,说线程的基本状态,以及状态之间的一个关系,其实这块还是涉及到生命周期的这个问题,呃,基本状态这个大家在答的时候呢,建议你就说咱们说的那个,呃,5.0的那个场景了哈,然后他们之间的相互关系,就是哪些方法的调用啊,导致这种状态会有切换啊是吧?呃,一些相关的方法啊,大家呢,也是直接看我们上面这个图片就可以了。Stop和方法,为何推荐不推荐使用?其实这个问题我觉得现在都很少问了啊。
33:00
对,他是过时了是吧。呃,因为呢,一旦执行。对,这个线程就结束了是吧。啊,那么这个呢,可能导致我们这个run方法呢,是不是有未执行结束的代码是吧。啊,有为。执行啊,结束的这个代码。哎,这是一个点,呃,另外的话呢,这个一旦stop,如果我们还是握它,还握有这个同步监视器的话。那其实这1STOP呢,他把这个同步同步监视器呢,也就给释放了,他的一释放呢,他本来还没有执行完,他还给释放了。相当于呢,他并没有正常的去释放这个同步加湿器,也就是说它操作共享数据呢,还没有做完。那么别的县城呢,就有可能会进来接着做,那么就有可能导致这个数据啊出现不一致的问题,也就我们所谓的县城的安全问题。啊,这个呢,也算是第二个点。啊同学,诶感觉因为没有新知识点呢,结果呢,一不小心发现说了个新知识点是吧。什么意思啊,就是说呃,Stop呢。它呢调用是吧,会导致。
34:03
哎,释放。同步监视器啊。啊,那就意味着话呢,我们这个同步代码块呢,可能没有正常执行结束啊,啊,那你要释放同步监视器的话呢,别的线上呢,可能就会来操作了,那由于你也没有执行完这个同步代码块,这就释放了,所以呢会导致呢数据不一致,也就是说呢,叫线程安全问题啊。这个能理解吧。OK啊,然后下边这个叫suspend哈,这个呢,咱们说呢,必须得搭配另外一个方法使用是吧。就这个resume搭配使用。啊,这个不用呢,主要说呢是会导致死锁是吧,就完事啊。好,Java呢,线程优先级是怎么定义的啊,这是我们提到的三个常量是吧。最大的优先级,优先级十。Max priority是吧,Mean priority。一啊,就是从一到十这个范围内的是吧,这个范围内的去定义就行了。然后扎瓦是抢占式的。
35:01
啊,高原高优先级的线程抢占低优先级的县城啊,这样啊。哎,如何理解限制安全,然后呢,呃,是如何造成的,这个咱们都讲过了是吧。诶,就是多个线程操作共享数据啊。导致呢,出现现成的安全问题了。哎,具体呢,就略了啊。好,然后多线程呢,共用一个数据变量需要注意什么?对,那就是线程安全问题。好,那多线程呢?保证线程安全,一般有几种方式?类似的问题很多是吧?那这块的话呢,我们就说了大方向呢,你可以说这两种方式是吧。再一个呢,就是同步机制。啊,另外呢,就是我们这个lock接口是吧。哎,两种大的方式,这个呢,再展开有两种同步代码块同步方法。OK啊。行,下边说用什么关键字呢去修饰同步方法。的,就是下边这单词得会写啊。啊,我写一遍。
36:04
这个不太好写,自己写一写。啊,Synchronized啊好用,它呢加在静态方法和普通方法的区别。对,那就是我们说的这个同步监视器不同了。咱们上面也说了啊,静态的话呢,就是诶当前类本身是吧,诶当然类本身当然了,这个其实是个对象哈,就是点class,然后呢非静态。对,这个就是这次了啊,这个你改不了它就是它啊,你只能说呢,这次的话呢,你看靠不靠谱,有可能不唯一啊。下一个说他俩呢,有什么不同?区别。区别是吧,区别啊,这个咱们在课件里边呢,也简单的稍微的写了一下他们的这个区别。嗯,对。这是吧,诶在这块稍微提了一下啊,行,这个我在课件里边也有写啊,当然你也可以看我们这个课件就行了啊,这个呢,因为在GC里边呢,还要重点的去提,所以呢,暂且呢,我们就不会聊这么多了啊。
37:02
下边一个就是当一个线程进入一个对象的C的方法以后,其他线程是否可进入此对象的其他的方法。对。你需要看其他方法是否也用的修饰了是吧?啊,其他方法是否。啊,是否使用啊,就咱们说的这个so去修饰。诶,这是一个另外的话呢,你还要看一下什么呢,如何用吸功带的修饰了以后呢,你还得看呢,它这个对同步加湿器同步加湿这是默认的吗。啊,它可能是Z啊,可能是当前累啊,啊,如果是Z的话,你也稍微看一眼,是不是同一个Z是吧。呃,如果呢,你是没有用CI修饰的,那当然呢就可以调用了。用形来修饰呢?也不一定不能。你看是不是同一个Z。你比如说回过来咱们的这个代码里边,我找这个实现啊,就拿它为例来说。
38:00
嗯,这个呢,是我们这个实现的这个方式cok,然后呢,在这个位置呢,我们就造了一个对象,我放到这三个里边了,比如说万一我故意的就给你再造一个,我叫S1,我这呢恰好用的就是S1。你想这个时候呢,如果你去调上面某一个同步方法了,这个呢还是那个同步方法,其实呢,根本就不影响调用。因为他俩是不是不同的这了。对,这个呢,小心一点啊,哎,我这儿呢,就还改回去了。你要注意一下啊,就是这个this的话呢,你也得看一下是不是唯一的。也就是说呢,需要看其他方法是否使用修饰,然后呢,这个诶同步监视器的。这个this啊,是否呢,是同一个是吧,只有呢,你是用它修饰的,且是同一个,那就不能够访问了。啊,只有当使用了。啊,S。然后且这呢啊是同一个。
39:02
啊的情况下。哎,就不能访问了。哎,就我们说的这个还能不能进入啊,就不能进入了。没问题是吧?下边说线程同步和阻塞的关系啊,同步一定阻塞吗?阻塞一定同步吗?同步一定阻塞吧?同步一定阻塞吧?对的啊,它不就是一个互斥关系吗?这个执行了,那个就执行不了,那个不就得阻塞的。阻塞一定同步吗?对,阻塞不一定同步哈。比如说你这块sleep了,那也不能叫同步啊是吧,哎,就是阻塞啊。诶,就是相当于咱们这个生命周期这块。哎,这不是上边生命周期咱们说的这个所谓的这个阻塞啊,这个所谓的同步,这不只是阻塞的这其中一种情况而已。啊,这个还有这么多种情况导致它阻塞呢。
40:01
好,回过来。下边思索,什么是思索?产生思索的原因和必要条件啊,这就是咱们上课讲的这个事儿。啊,就这个事儿,包括呢,如何去避免这个思索啊,整个我就把这个呢粘过来啊。哎,放到这就行,哎,避免思索啊,减。上啊,那就可以了啊。好,然后呢,这个Java中的notify和notify有什么区别。对,一个唤醒一个一个唤醒所有的是吧。哎,这个我们就,诶在。嗯,通信在这儿呢啊。哎,上面这个。嗯,放在这儿啊说呢,为什么wait和notify方法要放在同步代码块中调用呢?因为调用者必须是。同步监视器吧。哎,那你必须得放在同步代码块里面啊。啊,生产者消费者的代码让你去写的。
41:00
是吧,哎,斜尾代码这个你说来一点真实的吧,也能写是吧。诶,这个咱们就列了啊,诶深圳的消费者呢,作为咱们这这一章里边的一个算是还不错的一个案例,哎,大家下来呢,要练一练。OK,下边一个wait和sleep的这个区别,这个咱们重点写过了啊,在课件里边的这块。啊,CTRLC,那直接我们就粘过来了。好,不多说啊,下边单立说手写一个单例,还要现场安全的。上来就恶汉市了是吧?诶欧汉式呢,是线程安全的啊,诶或者呢,写这个懒汉式的话呢,你可以写咱们写在那里边儿的第三种方式也行,但是尽量要加一个我是吧。OK啊,或者你写一个安全的懒汉式啊。啊,就是咱们上课这不带大家写过吗。OK啊,或者你还可以使用这种内部类的方式。对,我在课件里边有这呢,我就不多说了。哎,手写一个懒汉式的单立模式解决安全问题,说为什么要这样去解决啊,这个还是同上就行。
42:07
诶,但是你不要呢,比如说他要泛泛的,就说说你手写一个单列模式,你要自己呢,写了个懒函式,而且呢,还不是安全的。这个呢就不太合适了。你要写的话呢,大家诶一定要写成一个安全的模式,虽然呢,他要没说诶是不是安全的啊,但是你这块要写的时候呢,一定要给他写成一个安全的。这就咱们整个这一章的一个内容。
我来说两句