00:00
大家好,我是海波老师,咱们继续来讲Java中的线程,前面的课程中啊,咱们给大家讲到了线程的同步和异步,咱们这里呢,画个图咱们理解一下,其实啊,咱们之前给大家讲那个异步呢,还是比较好理解的,大家看一下我这里呢有两个线程,我这里给他一个红色。然后呢,我写上它啊,咱们叫做线程一好了,然后呢,接下来呢,我再给它来,我们写上它,咱们叫复制,咱们复制一下,我变成一个蓝色吧,我这里呢叫线程二。啊,那这两个线程呢,你做你的,我做我的,咱们互相不影响,这个就是所谓的什么我们的异步,所以我这里写上它啊来好了啊,我说了,你做你的,我做我的,咱们谁也别影响谁,就所谓的不的感觉嘛,对不对。同步就不太好理解了,而且呢也不太容易操作,咱们之前给大家讲的时候啊,其实使用的是一种join的方式,什么意思啊,来复制,复制以后大家看一下,来过来以后这里我们复制一下放过来,我们现在呢,我们所谓的这个叫同步,对吧?同步,那么同步是什么意思呢?就是说我有两个线程,是呢,我把其中的一个线程给我加入到这个线当中去,也就意味着在我执行过程当中,我这边呢给它加入进去了,所以我这里画个小图标。
01:16
我这里呢,画一个图标,我放过来啊,放过来,放过来以后给它加到这里面去,就等同于啊建成一方成了它的一部分,所以呢,我这里用个虚线给它变成它就行了,哎,就这意思,所以呢,我这里呢,把这个线程二呢再往后挪一下。嗯,好了,给大家去说一下啊,大家会发现我把线程一放到里面去,那可不它俩就是同步的吗?为什么呢?因为线程一做完了才能到线程二吗?哎,这是我们当时给大家讲那个叫join方法的作用啊,但是其实啊,在实际的开发当中,我们的处理方式会有很多种,而更常见的其实是另外一种,比如啊,我们以前啊,去那个政府机构去办业务去啊,我们需要在指定的窗口排队,对吧,但是呢,办业务的人多,排的队伍就会很长,所以啊后来的人呢,就觉得呀,等的时间太长了,就总是往前挤呀,他想插队进去,那这样的话总是会产生很多纠纷,那现在好了,现在呢,就不用排队了,干嘛呢,都是电脑排号吧,就没有插队这个事儿了,那么这种方式呢,就等同于人为的增加了排队的一种处理机制,我来的早的就拿的号就比较小嘛,那么就先办业务嘛,那么来的晚的他的号就比较大,那么叫号的时候就会在后面去办理,对不对,这可不是你想怎么做就能怎么做了,不是说啊,你说你做你的,我做我的不是了,他就必。
02:32
必须有个等待的过程,对不对,你要来得晚,你就得排在后面,这个是没有办法,对不对?所以这也是所谓的一种同步操作,如果来得晚也想先办理业务,不行啊,你得排个队,前面不做完你做不了,你看这不是一种同步的感觉在里面吗?咱们Java的语法中啊,也有这样的处理方式,来我们这里呢,打开,打开以后呢,我们来拷贝,拷贝以后呢,我写上一个我们的零六啊,来那这里呢,我写上一个简称啊,咱们叫syn,叫single night,这是我们同步的一个意思啊,我点击OK。
03:02
就OK,以后把这个呢,我们去掉,咱们全去掉,去掉以后呢,我写上它啊,咱们就叫同步。我们说了,在我们当前的处理过程当中,我们这边有个class,刚才我有一个user,哎,有个user的,这个user干嘛呢?我们现在呢,就准备去做操作了,我们现在写上他public,我们叫做what,然后呢,写个test,写完了以后,同学们记住了,我需要在当前的这个方法的后面加上一个叫singleized,这个关键字,就称之为叫同步关键字,所以拷贝拷贝过来以后,那么这个时候呢,我们给它写上它叫它同步啊关键字,哎老师这关键字有什么作用呢?它的作用就是说它会有多个线程来执行,同一个方法的时候,只能有一个线程执行,同学们能明白我说的意思吗?来咱们说一下,就是多个线程它访问同步方法值只能一个一个访问同步操作,只要你加了这个方法,那么我们说了,我们当前这个方法就只能一个线程,一个线程进来,它不。
04:10
可能多个线程同时访问是不允许的啊,这个需要大家注意一下,其实咱们之前设计过这个问题,大家想想,我们之前给大家讲过一个叫做new,咱们叫哈希,还记得吗?叫table,这个哈希table是一个我们集合当中的类,我点击一下点点击以后你会发现它里面的很多方法啊,都加了一个singleize,这是一个同步关键字,这就意味着呀,当前的哈希table就是同步的,诶老师的同步那一个一个做不就慢吗?没错,哈希table的效率就要比咱们哈希map要慢一些,咱们那个哈希map可不是同步的,它是异步的,就意味着同一个方法多个线程,你访问你的,我访问我的,我们互相没影响,诶,这是我们的哈希map吧,但是我们的哈希table就必须一个一个去执行,所以性能上它确实慢,但是它慢是慢,但是它的优点就是它的安全,为什么呢?因为多线程同时访问的话,你也访问,我也访问,万一冲突了怎么办,对不对?所以啊,线程其实是有个安全性的问题呢。
05:10
我们这个哈希table就不用考虑了,注意啊,这里咱们说一下就可以了啊,好听一下,听完了以后啊,这个single关键字啊,除了给我们除了在方法的这个位置去声明以外,其实还可以呢,修饰代码框我们称之为叫同步代码框,可以来拷贝。这个我们的关键字啊,关键字还可以,咱们叫修饰,咱们叫代码框,称之为同步代码框,好了,哎,那怎么用呢?给大家解释一下,我们这里呢,写上一个星号,然后呢,写上它,我们叫做single night,你就把这个single night写上去以后,那么这时候呢,我得加上一个括号,括号里面写上它叫用于同步的对象,好,然后呢,我们写个花括号,花括号里面我们写上叫处理逻辑,哎,老师这个为什么不太理解呢?什么叫做用于同步的对象?
06:06
你处理逻辑好理解,就是个代码框嘛,你家那个同步诶,多个线程只能有一个进去去执行,这个可能也能明白,但是这个不明白的是用于同步的对象,这个怎么理解,为了给大家说清楚这个问题,我们给大家演示一个银行排号办业务的一个例子,咱们这里来给大家写一写,那比方说我们现在准备去银行啊,去办业务,但银行有那个什么排号的机器啊,咱们得先取号啊,对不对,而且呢,你是提前取号,为什么呢,银行到九点才开门呢,你不能说我九点钟我才去第一个吧,不是吧,你是不是得提前去啊,提前去以后先把号拿到手里,对不对?哎,是这样的一个情况,所以呢,我们这里呢,把这个过程呢,我们模拟一下,首先我就写上它,我们叫做一个class,我们就叫bank,我们叫做银行啊,银行有自己的独立的功能啊,哎,就咱们就假设是个线程对吧,你做你的嘛,那那个用户呢,诶我们也当成一个线程,你来提供服务,我来访问你的服务,对吧,那所以呢,我就写上它。
07:02
咱们叫thread,哎,我们这里呢,就有两个线程了,这两个线程干什么呢?很简单,我的U的啊,我准备要取号,哎,巧了,我是张三呢,我取的是第一个号,而我的银行呢,我开业了之后,我马上就叫号,就能叫到他,对不对,所以就有这样的一个功能,所以呢,我们这里呢,咱们就这么来啊,把这个去掉去掉,哎,别去了,住掉吧。助教,以后我写上叫public,咱们叫what,咱们叫做wrong什么意思啊,运行啊,那么我们这里呢,拷贝I的运行啊,哎,老师有问题啊,你的那个取号那个东西在哪呢?我这没有啊,所以呢,我在这里呢,需要准备一下,那我得需要准备一下,我这随便准备一个东西吧,就叫object,哎,或者咱这么写吧,就创建一个类好不好,咱们叫做class,咱们叫做number,诶有这么一个类,这个类呢,就好比那个取号机一样啊好翻过来。换过来以后我们写个number,然后你什么呢?咱们叫new number,诶就是它好了,那你这个new number a怎么写。
08:00
改完以后同学们想想,我们就靠这台机器来决定了什么,我们排的号啊,所以呢,我的用户呢,就准备什么呢,拿到这个取号机,哎,把那个号给拿过来,所以呢,这个number跟我的对象之间应该有关系,所以呢,我这样我们来public,咱们叫做U,然后呢,把咱们当前的那个number啊给我传过来,所以我写上它叫做number传过来,放过来以后我在里面啊写上一个provide,诶,我们写上一个number,好,Number放过来,放过来以后我们写上这个叫this第number,诶,它等于number啊就这个意思,啥意思啊,我拿到取号机了,我准备要取号对不对?哎,好,那么我银行也得有啊,你银行也得有相应的操作啊,对不对,为什么呢?它得触发那个取号机的叫号功能啊,所以我的银行它也得有这个取号机,对吧?好都有,那么都有了以后,我们这个功能是怎么跑起来的呢?同学们想一想,首先第一个就是我们的用户他要取号了,它取号的时候它是怎么取的呢?它这个时候。
09:01
不,我们的这个取号,你得排队取号,你不能说大家一块抢号不行吗?对不对,所以我们就得加一个关键字叫做同步关键字,这得排个队,一个一个做就是同步嘛,对,那你什么用来做同步呀,就是同步取那个号吗?所以number就是那个号啊,OK,然后呢,换过来。放过来以后里面写什么呀?我现在是不是的取号啊,所以呢,我现在就写上他,我们叫打印,打印以后写上它啊,写上他,我是啊,我是号码一啊号码一,然后呢,银行啊,银行还没开门。我需要等一会儿。也就意味着现在呀,你这种情况是什么呢?就是我现在拿到了第一个号,这银行没开门,我还不能去什么呢,不能办业务,我得等一会儿,他这个等怎么体现呢?这个等啊,就是我们的叫号机没开始叫号呢,一直等的第于我们的number,第二有个叫wait方法,这个wait方法呀,其实是我们的object里面的方法,大家看一下,我点一下,点点完以后,它是我们的object提供的一个方法,所有的对象都会有这个方法。
10:14
它就有个等待的过程,这个等待有异常发生,所以呢,我这里用快捷键out加回车,它提示我一下,把那个TRY开给我加上,加上了以后同学们我等待什么意思,100着,我们如果没有人让我去往下执行,我就不执行,我就等着好就这个意思,那如果要别人跟你说了啊,该你了,你该怎么办,我就该办业务了呀,所以说我在他的后面,我想一句话,什么东西呢,写上叫到我的号了,开,嗯。该我办业务了。好了,同学们,这是我的一套逻辑啊,我的逻辑就是先等着叫到我了以后干嘛呢?我就办业务了,那什么时候教到我了呢?那个我们的取号器他教导我了,对不对,就是他好,这就是我们当前用户的一个业务,当我们的用户的业务呢,我们已经写完了,那么回过头我们开始要到银行了,银行办理业务的时候,他不也得根据那个号来排嘛,对不对,所以他这里呢,也需要同步一下,把那个number放进去,然后呢,放过来,放过来以后我们的银行的等一会再开门呢,所以呢,我们的thad点要sleep,我们稍微的等一下,等完了以后,诶这里有异常,异常以后呢,给它加上好了,等完了以后,接下来你等了一会儿就开门了,那么我们这里打印一下,诶,写上它点了。
11:29
啊,开门,然后呢,开始叫号对吧?开开始叫号了,你这样的话呢,我们的那个排号器一开始通知我们的那个用户说啊该第一号一客户到我们的某个窗口去办理业务吗?那这样的话不就可以了吗?时间到的话,我们的这个银行不就应该让我们的排号去叫号了吗?所以咱们的number啊,他有一个方法,咱们叫做notify,有个叫做or,我是不是要通知到每个人呢?告诉你们现在是第几号了,对不对,那所以呢,我们这个就被通知到了,他被通知到了以后呢,我们的这个就可以继续往下执行了,诶这样的话就是一种同步的感觉,所以啊,我们这里有个叫notify all这个通知啊,它其实也是我们的object类当中的方法,就意味着每个对象其实都有这个方法,那么既然都有这个方法的情况下,那么好,咱们现在呢,就都可以去使用,没有任何的问题,我们银行啊和用户的这个功能咱们都写完了,那咱们前面这个程序该怎么做呢?很简单呢,首先咱们用户呢,先取号嘛,所以new u他先从这个取号器里面去取。
12:29
好对吧,所以来点start,然后呢,我们的银行上班了,咱们的bank,然后bank对吧,它等于new咱们的好了,咱们的bank,对写完了,完了以后,那银行是有取号器的呀,当他上班的时候,他就可以叫号了呀,可以bank.start。好了,我现在呢,就把用户和银行都创建好了,我们现在运行一下,看结果运行,运行以后大家会发现我们当前呢,我是号码一,银行还没有开门,我需要等一会儿九点钟开门,开始叫号,叫到我的号了,我该办业务了,你看这样的话,我们整个业务不就窜起来了吗?我先取号对吧,然后我等着,然后那银行开门,然后叫号,然后改我,你看这不就是一步一步出来的嘛,对不对,这就是一种同步的操作,好了同学们同步呢,咱们就讲到这里啊。
我来说两句