00:00
好,同学们,接下来给大家介绍最后一种引用,虚引用,那么按照我们的框架,也就是它phantom reference,那么它有哪些功能和作用?来先看理论知识的介绍。1233处第一个。虚引用必须和引用队列reference q联合使用,它不能孤立存在,必须要有一个引用队列,那么它的引用呢?是调用这么一个。Phantom reference类来实现。顾名思义,什么叫虚引用,形同虚设,和其他引用不一样啊。虚引用呢?并不管这个对象的生命周期。如果一个对象仅持有虚引用,那么就跟没有持有一样,虚嘛,形同虚设,在任何时候都可能被垃圾回收器。回收。也即它不能单独使用,也不能通过它访问对象。引用需引用必须和引用队列联合使用,它们两个绑定一块。这是第一个知识点。
01:03
第二个知识点。我们前面都说过各种引用的封装,对吧,也就是我们在这儿啊,假设啊,我们的。弱引用来有一个对套了一层,那么软引用soft有一个对象套了一层,我们用这个get方法或多或少都能获得里面的内容,但是非常抱歉。虚引用也有get方法,但是它这个方法总是返回呢,注意形同虚设啊。虚用它的作用呢,主要是跟踪对象被垃圾回收的一种状态,它不是用于业务逻辑处理和事情的方法,仅仅提供了一种确保对象被finalize以后做某些事情的一种什么通知机制。诶。那么既然它的get方法总是返回,那那么它有什么意义呢?好,那而且你还说通知机制,不这个已经有了吗?这个是在什么对象回收之前对吧?不可撤销丢弃之前实行清理操作,而这个需引用,最终它要是被弄掉了,会装到我们的这个引用队列里面,哎,好,这是两个概念啊,待会我们代码演示第三个。
02:10
作用是干什么呢?处理监控通知使用,那么设置虚引用关联对象的唯一的一个目的就是在这个对象被收集器回收的时候收到一个系统通知啊,或者后续添加一些其他的业务逻辑操作做进一步的处理,用来实现比finalize机制更灵活的回收机制。OK,好,那么你就记着两个点,第一个。虚引用的get方法永远返回,那OK,第二个点它必须和引用队列所使用,也就是说如果这个虚引用被干掉了,它将会装到这个引用队列里面,那我们在这个引用队列里面如果发现有对象了,说明有一个后台发生了一次虚引用的对象回收,那么这样的话,我们呢,就可以收到这样一个队列有东西了,发送后续的通知做进一步的处理,那么跟这个啊是两回事,他们俩各是各的好,一个是体现在对象finalize方法回收之前,此前遗言,一个是进入到引用队列里面,进入到队列里面有东西以后我再做什么事,那么来不妨我们来看一下我们的API phantom reference。
03:20
进来看一下,也叫虚引用,也叫幻象引用,对象收集器之后排队确定他们的对象可以被回收,注意。幻影参考通常用于安排什么事后清理操作,哎,在这个队列里面,如果我有东西了,我们事后清理通知机制等等,来,大家请看构造方法,就一个,你需用要去。包装封装的对象以及与之相关联的引用对列,创建一个新的换象引用对象,该引用引用给定对象,并在给定队列当中注册。OK,好,那么同学们。该的方法,构造方法就这么多,下面我们呢回到我们这儿,我们呢代码说话,那么在开始之前再次强调一个是构造方法。
04:08
OK,另外一个是我们的引用队列,我被回收前需要被引用队列保存一下,需引用OK,好了,那么下面整明白以后那么老规矩尿。Object,这个是我们的一个my object对象,那么第二个我们呢,直接先来phantom,那么来,那么这个时候我是my object OK,那么来,这是一个虚拟用的引用来实现。需引用OK,那么来第一个要装这么一个对象对吧,第二个它呢,要来这么一个引用队列,所以说前面我们呢也给你定义好,这儿呢要有个引用队列,我们呢也给大家装这么一个好,那么引用队列来。给你呢,全部构造完成,将它。
05:03
扔过来,OK好,那么在这儿我提前呢,设好了一些内存对象来,这个是这这个是这样的啊,我们在这块的话呢,我添加了啊,在这儿兄弟们添加这个Java虚拟机的参数,这个已经说过了啊,我就给它十兆,OK好,设置好,相当于说我整个现在堆内存就是十兆,那么现在呢,先来验证第一个我这个就是一个什么。需引用点get方法,我确确实实用了一个object,那么换以前我应该是获得一点什么东西对吧,但是现在非常抱歉,我们呢这个get方法。来看看。有什么东西反馈给我们呀,就是个那听懂了吧,所以说回到我们的虚引用的队列和脑图知识结构,虚引用的get方法总是反馈什么,那OK,它呢,无法访问对应的引用对象,好,那么下面我们呢,也就说你要拿它来干什么活,这个呢就不要多想了,没有任何意义,那接下来啊,我们呢,干这么一个案例。
06:09
这个信用呢,也非常难模拟啊,但是呢,我们尽量的尝试一下干这么一个事儿,两个线程,那么现在呢。我呢,先来啊,List。这个呢,是一个字节数组啊。List等于list,那么弟兄们,换句话说,我往这个list里面不停的填充对象,明白吗?我现在有两个线程。这个呢,是我做的一个list容器啊,那么现在我干一件什么事呢?T1,这个动刀。现在我要错。你晓得的,那这个呢,我呢就干了一件很操蛋的事儿,List点艾六字节数组,那么一乘以1024乘以1024,换句话说这样的话,我这这个弯腰戳是不是不停的往这个list里面一兆一兆的加内存,刚才我们后台已经给大家演示了我多兆多少兆才十兆,那么你晓得的,我现在一运行只给你十兆的内存,那么你总有一天会打爆,只要Java虚拟机里面对内存里面东西对象多了,它是不是自动会触发后续的GC和垃圾回收机制啊,那么这个时候我们回收的时候来看看我们会有哪些情况,那么来。
07:25
也不多啊,我们每500毫秒呢。干一次啊,那么在做的过程当中,我们也给大家呢,再继续演示啊,我每添加一兆以后,我每次用get去取,看看有没有什么东西,那么这个时候啊,再次给大家。List OK,那么假设打出这么一句话,就说明我每一次啊,这个list呢,都加进去了,并且我这个get应该每次都是,那再次给大家验证一下,这个需引用这个get的方法永远返回,那好弟兄们,这是我们的什么第一个线程它干的活,那第二个线程呢。他呢干的活呢,跟前面的就不一样了,我也不做什么,我这儿呢干掉。
08:06
那你要干一件什么事呢?我们这儿是不是说过有一种东西叫引用队列,对吧?也就是说如果说我发生了底层Java虚拟机把这个虚引用给干掉了,干掉的话,这个对象封装的这个虚引用被干掉了,它应该装到这个队列里面,OK。所以说我这。直接过了这儿,那么如果说。这个。引用,OK,那么你看我在这个队列里面看看有没有值啊,如果说这个队列它不等于烂了,那么说明什么?已经有虚对象加入了队列,听懂这个意思吗?那么就是要虚对象。被回收啊,虚对象回收,加入了队列,就这么个意思,这么说能跟上好,如果这句话打出来,那说明什么?我们的虚引用被干掉了,加入到了这个队列,我们来验证一下,那么这个时候由于是关要戳,我们写小心一点啊,这个是break瑞克,那么上面我就不管了,我就粗糙点,我就是不停的戳一句打爆他,让他。
09:14
报这个OM就行了,那么好。这一切都完活以后,T1干一件什么事,T2干一件什么事,我们来试一下,那么这个呢,呃,是一种随机的啊,他加的时候看看会不会打印出这些话,会不会打印出我们这个话,那么演示的过程当中不见得第一次就成功,但这个意思,那么同学们应该大家能够明白,好,那么同学们请看一下我们呢,不停的弯腰处,然后大家请看。马上就会看到啊,因为我分的比较小,我这个时候就是十兆内存,那么一兆一兆的马上去给它加,那么好有对象马上就不够了,要被回收好,这个回收的对象可能是这个字节这么说能跟上,但是由于我不停的,你看这个nu是我这儿需引用get得到,那然后list.i说明这个对象增加成功,但是Java虚拟机在也是在后台呢,已经检测到啊,你不停的要出出出出处加对象把我。
10:08
慢慢的被变得膨胀了,我也在收着,直到后面加不进去了,报oom Java keep space对内存溢出了,注意有需对象回收加入队列,那么这句话打出来说明什么?我们一定有,因为内存紧张了以后越来越多嘛,List艾导致呢,这个对象与之相关联的也有东西了,那么发生了,我们的需引用好,那么这个时候。虚拟回收也就给大家呢,说到这儿好,那么呢,这个呢不是我们的重点啊,我们只是说复习一下强软弱虚四大引用,主要是通过弱引用来说清楚local,那么至于说Java虚拟机的知识,那么请大家呢,可以去参考上硅谷宋文康老师的视频,那么最后给大家说一下GC root跟可达和四大引用的一种小总结,来弟兄们。这个呢叫根,我们都明白啊,只要是从根开始,这个线条可达这个对象就不会被回收,那么来看一下纯黑色前以后。
11:04
OK,即便发生oom了,也不会回收。第二种这样呢,是soft软引用,内存紧张时回收处于临界,地主家有余粮不跟你计较,但是地主家也没有余粮了,内存紧张了,马上回收。第三种需引用为reference,再次强调,我们讲的是local,主要是用它。弱引用只要有GC马上被回收,OK,第四一种虚引用,那更是了,虚引用必定会被回收,OK,那么所以说他们的层次啊,是一个比一个弱,那么最后这两个啊,比如说它们两个之间互相引用,但是跟我们的根。不是从root开始的,通通被垃圾回收,OK,这个就是我们的四大应用相关的理论和案例介绍,好,那么最后我们来复习一下。大家一定要注意啊,我们现在呢,干一活,Ad local引用等等等等啊,我们在这儿,那么请大家看就这个,比如说我们的这个销售额,就这么一个东西没问题吧,那么这行代码我们干一件什么事呢?
12:10
第一个。所有的local对象引用在占这面,第二个这个线程,第三个T就是我们丢进去的,比方说我们set这个方法扔进去一个对象,那么它到最后这个N垂对象里面是我们的那个value那个值啊,这个呢,我们也已经看过源码说过很多次了,那假设啊,我们这一赛,那么弟兄们呢,都清楚在这块它到底是干了一些什么事,那直接create的时候,我们都清楚这块this和value分别是什么,好对应着我们的,请看啊。对象,比方说thread t1等于new的一个T1,一个对象,每一个thread,每一个人还记得我们这个三角形人身份证卡片和身份证信息吗?那么我得到一个自然人对象,一个县城,主要是得到这个人的,比方说TV建指队啊,身份证上面的什么照片啊,名字啊,身份证号啊,这个户口地址啊等等等等,但假设我们最重要的就是两个啊,身份证号码和人的姓名,那么这个就是一个TV建职队,那么这个TV建职队每一个12的对象内部都有基于threat local里面的一个TH的local map,这么一个静态类不类,而它其实说穿了底子就是一个。
13:23
实现了弱引用的一个N垂于对象,它就是个KV间值,对,那么这个value就是我们set进去的这个value对象,而这个K,注意一定要说的很明白。我们在这。说过了,所local里面的静态内不类对吧?它这是个ENT,实际而言是一个weak reference是个弱引用,那么隔到这儿我们就会明白,这个value是我们设进去的值,这个key就是一个th local弱引用对象。好,那么来吧,隔到这了以后我们会明白,总体而言,这个local只是作为一个K若引用的K。
14:05
从理论到源码,OKENT继承了weak reference是一个若引用它呢,Key就是它,Value就是我们设进去的这个值,具体你写的好了,说穿了它就是个壳,真正存储的是这个local map,每个线程对象都维护着一个local map的引用,每个对象,每个的线程对象都有所local map就是所local的。内部内用N来进行存储,那么两步,当我调用set方法的时候,实际上就是往我们的这个什么。Map当中设置值key就是我们的所local value就是我们传过来的对象,第二个我们get的时候,实际上也就是往这个map里面去获取值啊,这个key也就是我们当前对象的的local,那么所以说所有local本身并不存储值,它只是一个壳子。它只是把自己作为一个key,让线程从有local map当中获取我们的value,正因为这个原理,所以呢,每个线程的所local都能够实现什么数据隔离,获取当前线程的局部变量值,不会受到其他对象的影响,好,那么同学们,这个就是我们重点要给它复习和掌握的强软弱虚四大引要,那么接下来我们要面对这个问题,他为什么要用弱饮要那么。
15:27
为什么要用若引用?不用行不行?会产生哪些问题呢?有两个坑,一个是为什么要用若引用?第二个如果这个key为难,你会怎么办好?后事如何,且听下回分解。
我来说两句