00:00
各位同学大家好,刚才呢,咱们完成了读写所的基本概念的说明,那下面呢,咱们来写一个具体例子,通过这个例子给大家演示一下读写所这个基本操作,那咱们写个什么例子呢?咱们就模拟一个缓存的这个过程。因为各位同学知道缓存嘛,咱是不是能往里面放那种,从里边是不是能取那种,那我现在就模拟个过程,比如咱们先用一个最原始方式实现,用多线程,我们向map机构中放数据,从map机构中取数据,就模拟缓存的过程,往里边放,从里边取,咱们用多线程方式把这个做到,那下面我们就来写下这个基本的这个代码。我来写一下,咱们先写一个最基础实现,然后再加上这个读写索方式,把它做改造。那首先我在里边加个包,这个包比如我就叫做read write,就是读写锁,然后这个创建之后在里边呢,我来创建一个类。
01:10
这个类,比如说我给它起个名字啊,咱就叫这个read。Right。索log读写所,然后这个创建之后,在里边我来加上它的相关内容,呃,这么写其实可以啊,咱为了防止它有冲突,我把名字稍微改一下,我叫这个read write log DEMO啊,把名字改一下,然后改完之后按照咱们这个多线程的编程步骤,首先是不是先写个资源类啊。创建一个资源内。那我写一下,我来一个class,我们叫这个买cash。然后在买开始中,首先我先定义一个属性,这属性就是创建一个map集合,因为咱们要往里边加那种,那我来这么一个map map中加上它的key,就来一个词缀value object,然后咱们写个map,等于直接new上一个哈希map。首先把map集合我们先进行这么一个创建,这是咱们的第一步操作。
02:21
APP集合里边呢,咱们要不断往里边放内容,又要从里边取内容,这里的内容要不断发生变化,所以咱们给它加上一个关键字,叫这个我time,就是让它因为表示这些数据不断会发生变化,咱们要不断往里面放那种,又要不断从里边取那种,这是咱们的第一个属性定义,然后定义之后,下面我们写两方法,第一个方法就是向卖结构中放这个数据方法,然后第二个从里边取数据的方法,那咱们来写一下,首先我写第一个方法。咱们来一个public,一个we,我叫做put put里边因为咱们放数据是不是一个key,一个value,所以我加上一个key,咱们加上一个string。
03:13
Value,我就来一个object。Y6,这是我们加的两个参数,然后加完之后往里边放数据,咱为了明显,首先我先做个输出,就输出这个当前的线程名称get name后面加上一个提示,就是说这个线程正在往里边,就正在做这个。写操作。然后咱把它那个写的那个key的名称给它也输出一下,咱为了后面测试方便,然后这个做到之后,为了效果明显,咱们让他先暂停一会儿,因为写的话嘛,需要写一会儿,所以咱给它暂停一下,或者后面效果明确,用这个time union点这个咱就加个毫秒数。
04:05
点上一个叫sleep,咱就让他等待这个300毫秒,这里边有一场。加上一个TRY,那我们来处理一下,所以这是我们的第二部分,然后这个选完之后,下面呢,就往里边来放这个数据,我们就加上map.put里边放这个key,还有它的value,然后放完之后,最后我们加个输出,说现在这个线程这个数据已经写完了,或者说已经放完了,咱们来加上这么一个处理,就是它已经。写完了。把这个啊,咱们加上这么一个提示,所以现在我们就完成了这个方法,向map机构中放内容,咱们通过put方法往里边放数据,然后里边加了输出,这是正在写,这是已经写完了,这个完成了,完成之后呢,下面我们再写个方法,从map中来取这个数据。
05:09
咱们加上一个public。Object取数据嘛,我就叫get方法,咱们取要根据它的K是不是来取,所以我加上它的这个K。然后写完之后,下面呢,咱们也是做一个输出,首先我先输出当前这个线程,比如写一下现在正在做一个读取的这个操作,然后根据K来读取,然后下面让他也是先暂停一会儿,我们加上一个这个。然后暂停之后,我们来取一下这里边,比如说我在外边呢,我先来一个变量啊,咱们来一个object,我叫result。然后咱们result。等于这个map.get加上咱的K,把这个值取出来,取完之后我们再做一个输出,就是输出说他已经获取到了,或者已经取完了。
06:10
这么写啊,就是它已经取完了。这样的话,咱们把这个结构完成了,完成之后最终把这个result我们来最后输出,所以现在我就快速把这个资源类就完成了,咱们看一下第一个第一个属性外,因为它是一个。不断发生变化一个属性,然后第二个写了一个放数据方法,往里边放内容,然后包括下面写了一个取的这个方法,从里边读取数据。正在读取,取完了,正在写,已经写完了,这个资源类的方法就完成了,完成之后下面呢,咱们就来创建多个线程,把这个最终做个测试。
07:00
那我们写一下啊,首先我把这个买catch给它先扭一下,为了咱们一会儿能进行调用,然后这个选完之后,下面呢,我们来创建多线程,因为咱们要实现是不是要读还要写呀,所以我现在我这么来做,我写两段线程先建,比如说我先建这么五个线程嘛,往里边放数据,再建五个线程从里边取数据,就是咱们一边往里边放,一边从里边取,那我现在来做操作,首先我创建就是线程。往里边。放出去。然后在创建线程,从里边取数据,那咱们来写一下,我这里边写一个负循环,比如咱们循环I等于一。I小于等于5I加加。下面我们直接比如我new上这么一个thad,里边加上这么一个拉姆的表达式,在拉姆的表达式中,我们往里边加入它的内容,咱们就要用MY开中这个put方法往里边加入数据。
08:12
比如现在啊,我在里边,呃,我就加上这么一个变量吧,啊,咱们来一个。啊,因为这里边啊,如果你直接加这个I,它会有一个小问题啊,给大家说一下啊,什么问题呢?比如你看我这么写,比如加一个I。它这个值也是I,然后你看啊,里边报错了什么错呢,他告诉我们啊,你这么写的话,这里边呢,应该是一个。是不是一个final的这么一个变量,应该是一个final的,所以咱这么写,你这个不好改成final,为了方便我这么来写,第二一个final,咱来一个int等于一,然后里边用um来替代咱这值,因为它每次做操作啊,我往里边就不断加入这个数据,所以咱们用这个来做这么一个处理。啊,那这里边我给他快速来写一下啊,这个操作。
09:04
那咱们来看一下啊啊,这里边我写上一个叫am,因为它一个字符串嘛,再加个引号,呃,这里该写成I啊,不写错了,不是一,然后这里边就是它的值也来个amm,加上一个字母上,这样的话就往里边放了数据,放完数据之后加上它那个线程名称string.value of。点上一个其他的方法,所以这样的话,咱们把第一部分线程完成了,往map集合中放数据,然后这个选完之后,下面咱们用同样的方式再来建五个线程,然后从里边我们来取数据,那我写一下啊,买K,点上这个get方法,里边加上你的key的这个名称,因为它的key都是nu。这么一个效果,所以现在咱们把这个过程我们就最终完成了,里边就是这么一个特点。
10:05
各位把这个给知道。然后这个做完之后呢,下面呢,咱们把这个效果咱来试一下,看一下目前这么写之后,这个效果是否能正常运行下去,所以咱下面把这个我们来做一个测试。那我们来试一下啊,大家一起来看一下目前是什么样的效果。大家注意啊,你看我写的说这个一,这些应该是正在做写操作,然后这里边说正在读这个二这个操作,但你注意啊,这个二是不是应该是你写完之后才能读,而它这里边就是你发现问题就出来了,我这个二正在写,我这里面是不是正在读,而我二因为我没有写完,我读的时候是不是肯定读到正常效果,应该是我写完之后是不是才能进行读,所以目前问题就出来了,你在写的时候,但是还没有写完,他就开始读,这读肯定是读到的,所以咱目前问题就出来了,这是咱们没有加上这个所的时候造成问题,我没有写完就开始读,读肯定是读不到的。
11:17
那这个问题怎么解决,人会加上锁来处理,在doc里边给咱们提供一种锁,就刚才咱们说这个叫读写索,通过读写锁把这个问题我们就可以解决,那咱看一下读写锁我们到底该怎么去用。首先啊,看一下这个API文档中,咱们找到Java u con look这个包在里边呢,我们看到一个接口,Read write lock,是不是读写锁,读写所是个接口,里边有个实验内,这个实验内叫read,安track read write lock,咱通过它就能实现咱的过程,然后在这个时间内中,你看到啊,这个叫readlo。
12:02
是不是这个读索,这个叫write log是不是写索,所以咱在读的时候可以加个读索,在写的时候给它加上一个叫写索,所以咱们下面就可以把我们的代码通过读写锁做个改造,然后最终我们再进行这么一个测试。那下面咱们把它就来改一下啊,咱们看怎么来做,给各位来写下啊。首先第一部分。咱们在这个买K之类中呢,先创建。这么一个读写锁的一个对象,那我来创建private,我们叫read write lock,比如说起个名字。啊,叫这个read write lock,呃,咱为了好写啊,我就叫RW,这个lock,就read right lock,等于new上这么一个叫read track read write lock,就创建一个读写所的对象,这个我们就创出来了。
13:03
然后创建之后大家看啊,我这个方法是往里边放数据啊,就是往里边是不是写数据啊,所以咱们写数据之前,首先给他先加上这把锁,就先添加上一个。写锁,那咱看怎么做啊,用RW lock点上这个方法叫做right lock点上一个叫lock方法,咱现在可以加锁,然后你看这个返回叫这个lock,咱们再点上一个lock方法,是不是就能加锁,所以这是我们写的第一部分,把它先加锁。然后加锁之后,下面呢,咱们写代码,就刚才里边这个输出的过程,我把这个啊都放到我们这个TRY开里面去啊,就是下面代码我也给它放到这个TRY开里面去啊,都放到这里面去。然后这个我们洗完之后,最终这个锁你洗完之后是不是要释放,所以咱放到这个,放到里边做一个锁的这个释放就释放这个。
14:10
解锁。那怎么做呢?咱们用RW.lo点上这个rightlo,点上unlo又来释放这个解锁,所以这样的话,这个部分我们就完成了,这个完成之后呢,下面呢,咱们用同样的方式把这个读索给它加上,在下面代码中,首先我们先添加上一个读索,因为你要取数据嘛,肯定是叫读索,所以我们加上一个RW lock上这个叫read log,点上log方法添加上一个读索,然后下面部分我还是放在这个TRY开里面去啊,都给它分过来。包括下面代码,我给他也是做这么一个复制,就是我们的这个代码。
15:01
给他啊,我都拿过来。呃,这个放到上面啊,为了咱最终能做那个旅退。然后这个选完之后,最后咱们把这个读索是不是也要做一个示范,那我们加上一个半理。价格。注射。释放。读索,最终rwlo点上readlo.unlock所以咱们现在把这个代码我们就最终完成了,这就是通过读写锁在里边这样一个操作。咱们在。放数据写的时候上写作,在你取数据读的时候加读索。最终效果我们就完成了,完成之后咱们下面把这效果最终来测试一下,看一下最终的这个结果是怎么样,也就是咱们加了读学锁之后,它最终会变成什么样的,因为刚才咱也看到了,我没有加锁的时候呢,它的问题就是在这里边我们造成了出现问题,就是我在写的时候还没有写完,里边是不是在读,你读肯定是读到的,所于刚才有这问题,当然现在这问题我们通过读写所可以做过解决啊,咱为了明显啊,我在里边也加上一这么一个sleep,就让他看到更明确点啊。
16:21
这个它也加上啊。给它加一个Z,然后现在我们执行一下,看一下最终的结果到底是怎么样的。那咱来看一下这个特点啊,大家注意看,这是我刚才说这特点,问各位啊,我们说这个邪所又叫什么所。是不是叫独占所呀,独所叫什么所,是不是叫共享所呀?所以你看这里边啊,我二正在写,写完了,一正在写,写完了,四写写完了,五包括三是不是都是写写完了,然后他们都写完之后,你看这里边12345都在干什么,是不是都在读啊,因为它叫共享锁,然后这里边告诉我们最终这些是不是都读完了,或者说取完了,所以现在咱们通过读写锁把这个过程很好的做演示,写索叫做独占所。
17:14
读索叫做共享锁,现在通过这个例子把这个效果最终做到了,所以大家啊,第一个你要记住读写锁的特点,包括读写索怎么样会发生词索,另外就是读写索到底该怎么去用咱们刚才提的代码,通过这个例子把这过程做了一个实现。
我来说两句