00:01
在刚才内容中呢,我们通过了site的关键字实现了一个模拟卖票的效果,通过它大家至少能掌握多线程编成一个基本过程。而刚才我们在用这个四个ne的关键字的过程中,大家也看到了这四个ne的关键字,它的上锁和解锁是不是由它自动完成的,比如我现在我一个线程在调它的时候,那我就为这个里边上锁,然后当我这方法平行之后,是不是它会自动释放锁,然后别的线程可以抢到,最终再完成它的切化操作。而现在这个上锁和解锁过程,其实咱们也可以手动控制,那手动怎么做就可以用到我们的这个接口,叫这个lock接口,Lo接口,是由doc中提供的一个针对锁的一个接口,它能够手动实现上锁和接锁,那在下面我们就通过这个log接口也来实验一个同样这个卖票的效果。
01:01
那咱们看一下怎么做,首先我们先看一下这个log接口,然后这个接口呢,咱们找到这个API文档中,通过文档来看一下logo接口,大家看这个包,Java u concurrent logs。然后这里写到它是为锁和等待条件提供了一个框架的接口和类,它不同于内置同步和电视器,然后这叫lock接口,在lock接口里边,如果咱们用的话大家看一下啊,这里写到lock实现提供了必须使用使用nice方法和语句可获得更广泛的锁定操作,就是它比这个ne关键字功能更加强大,那lo接口咱们打开来看一下。然后各位看啊,Lock是一个什么接口,然后有接口就会有什么是不是实现类啊,所以它里边有很多实验类,咱们现在先说第一个实验类,这个实验类叫retralo,另外还有两个retro的read rightlo,就是一个读写所,这读写所咱们一会儿会说到,就是里边这个内容,读写锁目前先说里边的这个所叫re安tra lock这个名字叫做可重入锁,虽然一会儿通过lock,那我们就new这个可重入锁对象,最终实现咱的功能,这个写法在里边有它的具体例子,那我们来看一下啊,我把这个点开。
02:34
然后大家看它例子中啊,首先第一部分,首先new这个叫可重入锁,然后在操作中大家看这两行代码。这是什么?是不是就上锁这是什么?是不是就解锁,就是lo是上锁,Unlock就是解锁,或者说叫释放锁,所以我们现在就用这个叫可重入左方式,把这功能给它最终做到我写一下。
03:01
可重入锁,那什么叫可重入锁呢?给大家解释一下啊,这个锁有什么特点,你看这个词。可重录。重是不是就重复的意思就是你可以重复使用,那这个什么例子呢?给大家举个例子啊,这例子可能不是特别恰当,但是能说明咱这问题,这是大家注意,各位同学应该都去过一个地方。叫厕所,应该都去过厕所,比如咱们去的时候,咱是不是要依次进入厕所呀,比如现在啊,我进入厕所之后,那我干什么,我把厕所的门给他是不是锁上,你在门外是不是等着我,等我出来之后,那你进入,你进入之后是不是要把那门锁上,然后后面人在等待,这就叫可重入锁,每个人进入上锁,出来之后解锁,下一个人进入再上锁,出来之后再解锁,以此类推,这个过程就叫做可重入锁,而咱现在就用这个log中的可重入锁,咱就来实验一下这个卖票的这么一个例子。
04:07
这个各位给他知道啊,然后这里边look跟S有一个简单的比较,我们来看一下啊,这个过程这里写到这句话刚才读过了啊,就是它比这个S有更广泛的操作,然后两个区别是什么呢?Look不是Java语言内置的,S呢是Java中的关键字,Lock是个类,通过这个类可以实现同步访位。另外lock和SNE它们非常大的不同是什么呢?SNE是自动上锁合释放锁,而需要咱们手动上锁和释放锁,这是他们一个最大区别,那下面咱就通过lock把咱们刚才这个卖票的例子,我们下面再做一个实现,让大家感受一下这个lock借口到底咱们该怎么进行使用。
05:01
那下面我把例子我们就来写一下,然后咱们还是来到这里边,首先我在这过程中呢,我再建个包,这个包我就叫这个log。然后这个包创建之后,在lock里边呢,我们同样建一个卖票的这么一个类,为了区分,我前面都加上这么一个叫L,表示这个卖票。我们叫LT,然后创建之后在里边按照咱们刚才的操作步骤,各位同学应该很熟悉这个过程了啊,第一步是不是建资源类,建属性,建方法啊,这步骤和这些复制,然后第二步就是咱们创建这个线程,去调用资源类中的操作方法。这是一个基本步骤,那下面我在里边写一下,首先我们先建个类class,咱们叫这个LT。就是为了区分一下,然后在里边呢,创建咱们的属性,还有它那个操作方法,那我写一下啊,第一个属性。
06:06
就是它的跳的这个数量。我们来一个叫private。In,这个叫number,这个值是30,这是里边的第一部分。那写完之后呢,下面咱们创建资源类中这个就是卖票的这么一个方法,那这个方法我写一下,我来一个public we名字我叫这个sal,这个方法上面咱就不加那个site的关键字了,我们用look进行实现,那怎么实现呢?首先我们在上面呢,先创建一个叫可重入锁,那我们来创建。可重入锁怎么创建,我们来一个private,咱们叫这个final,或者说你看到它的文档中,其实就是里边的这个代码,我把这个代码给各位直接就过来,咱们建一个叫可重入索,就这个名字re安tra lock,然后创建之后,下面呢,我们在卖票方法中做难的功能,首先咱的第一部分。
07:14
就是我每个线程在操作卖票方法的时候,首先咱是先给它上锁,然后上锁之后,最后我们要做一个解锁,所以在里边首先咱先上锁,用漏,里边这个方法就叫做漏方法,这个就表示上锁。另外还有一个叫解锁,或者说叫释放锁,Lo里边的方法叫unlo,这表示解锁,然后咱们上锁之后在里边来做这个操作,就是判断是否有这个票可卖,如果有的话,让他数量就减一,这个方法刚才咱们写过,那我就快速写下。如果说number大于零,那就表示有票,有票的话,那咱就做一个输出right点叫current threat.get name,然后这里边我们来输出一下,就是咱们提示说目前我们这里边就是已经。
08:15
卖出了。这个多少张票,然后用这个number点点点点之后我们再想一个值,就是它目前剩余多少张票。啊,咱们也是做这么一个提示。剩余多少张票这个number。所以现在这个结构我们就写出来了。然后写完之后呢,就是代码这么写是可以的,但是咱们给头做一个完善,因为大家注意啊,比如我现在这一行是不是叫上锁,这一行是不是操作呀,当我在操作过程中,比如咱们目前啊,突然出现了异常,如果你有异常的话,那这解锁是不是就不能解了,或者这锁就不能释放了,那别的线程是不是只能等待,所以咱们就把这个解锁或者释放锁操作,咱给他做一个处理,也就是类似于这种场景。
09:13
这个各位应该知道是不是可以写到finally中,Finally什么特点,不管有没有异常,是不是都会执行,所以咱现在就把它写到一个班中,那我把它做一个完善,我们加上这么一个TRY,开这么一个结构啊,因为咱们直接来一个finally。然后在这个TRY里边把这个判断的方法打进去,在这个finally里中把解锁方法打进去,这么写的话,不管有没有异常,是不是都会做这个所得释放,所以咱们目前就把这个资源类,包括它的属性,包括它的操作方法,我们就完成了,这时候我们解这个代码。然后写完之后我们看第二部分,第二部呢,咱们在里边就做一个最终的调用,首先我先new这个对象,就是这个LT。
10:06
我们叫这个T等于new上这么一个LT,把这个对象创建,然后创建之后下面呢,咱们同样创建这么三个线程,然后把这个这种实线。创建线程方式,咱们刚才都说过了,是不是直接谬这个对象就可以了,这么写是没有问题的,但是咱为了写法更加简单,各位同学学应该知道啊,在咱们JAVA8中有个特性叫做拉姆的表达式,比如说我们这个new run ne的部分,咱用拉的表达式把它是不是可以做个简化呀,因为它里边就这一个方法,然后这个reable,大家看一下,看这个主点。这叫什么?是不是叫函数式接口啊,所以证明它可以用到我们那个拉姆的表达式,包括里边有这个run方法,所以咱们现在就把这个线程创建,我们直接用这个拉姆的表达式把它做一个简化。
11:08
那我来写一下啊,上一个thread里边加上一个拉表示。就写上一个括号右键头,然后加上大括号,在大括号中我们加上里面那个具体这个逻辑啊,咱们给他写一个问方法中我们来实现啊。然后咱们先创建第一个线程,然后在这个写法中呢,就是写的跟我们刚才是一样的,只是说咱用这个代码给它做这么一个简化啊,那我们来简化一下啊,首先在这里边呢,咱们还是加上一个负循环,I等于零,I小于40,在里边调一下咱们那个TK里边这个方法。我们来调一下啊,里边这个最终这个方法,然后咱们做个实现。啊,咱们给它快速写完,现在我们在里边调用这个TK的中这个方法,我们来实验一下啊,我们来调一下,呃,这个位置应该写到这个问里边去,咱给它换位置放到问方法中,然后下面我们来做一个调用,调用T的中这个角再有方法,然后咱们给这线程加个名字,比如说我们的第一个线程就叫A,所以现在这个完成了,最终我们调这个,注意别忘记啊,我们最后要调里面那个叫star的方法,最终实现。
12:31
呃,我们来调一下啊。里边这个叫拉方法,所以现在咱们这个线程,我们就通过这个拉姆的表达式方式创建出来了,用同样方式我们再创建第二个线程,第三个线程,第二线程我叫BB,第三个叫CC,所以咱们目前lock接口到最基本使用这个代码我们就写完了,就是一个做法,咱们来看一下啊,核心是在这里。
13:01
首先new一个叫re entra lock可重入锁,用lock上锁,在释放锁中间是它的操作,然后又写了三个线程,最终做调用三个线程写法,但是通过拉姆的表达式把这个最终做这个实现,然后各位写的时候注意啊,别忘记调这个大的方法。这个完成之后,下面呢,咱们把代码。我们来做个测试。看一下最终的结果是怎么样的。那我们来试一下啊,大家看目前这个票是不是都卖出去了。就是最终实现出了我们的效果啊,包括这次是BB都卖出,刚才是A啊,当然你多次执行它的效果,每次应该是随机的,所以现在这个接口就完成了,关于lock实现咱们卖票的这个例子。这各位大家要知道啊,然后这个说完之后呢,下面给大家说一个细节问题,也就是里边的这个方法。
14:01
大家考虑问题啊,就是我现在啊new这个threat,然后我调用start的方法,比如说这个时候我这个线程创建了,我比如我调色的方法的时候,我这线程是否会创建。大家想一下是否会创建。我强调啊,这个答案是怎么样的是不一定的,就是他可能会创建,也可能不会马上创建,可能一会儿创建,那为什么这个样子,给大家说一下啊,咱们看它的源码,点到这个start里边,然后在他的里边,大家看它下面有这么一个结构啊,首先是一个标志位的判断,能加到组里边,这里边有一个start start这么一个就是一个标志位,然后下面它调了一个方法,就这个叫START0方法,那我们进入到方法中,大家看一下啊,我们看这个关键字。叫什么?是不是叫native native什么意思?就是它现在这过程中呢,我们要调到到native这过程中,Java代码就无能为力的,其他部分就是去调操作系统完成,比如我最终啊,我这过程中是由操作系统决定的,比如我现在我要建这个线程,然后把这个指令给操作系统的,具体什么时候创建,由操作系统决定,比如说我刚才提到的你一定要死的方法,这线程是否会马上创建,它不一定可能马上创建,也可能等一会儿创建,比如这个时候呢,正好操作系统很空闲,让他给你创建,这个时候可能操作系统正好很忙,他可能等一会儿创建,也就是里边用到这个A,然后最终把这做到。
我来说两句