Java ~ Reference ~ ReferenceQueue【总结】

news2024/11/17 11:27:58

前言


 文章

  • 相关系列:《Java ~ Reference【目录】》(持续更新)
  • 相关系列:《Java ~ Reference ~ ReferenceQueue【源码】》(学习过程/多有漏误/仅作参考/不再更新)
  • 相关系列:《Java ~ Reference ~ ReferenceQueue【总结】》(学习总结/最新最准/持续更新)
  • 相关系列:《Java ~ Reference ~ ReferenceQueue【问题】》(学习解答/持续更新)
  • 涉及内容:《Java ~ Reference【总结】》
  • 涉及内容:《Java ~ Reference ~ FinalReference【总结】》

一 概述


 简介

    ReferenceQueue(引用队列)类是Reference(引用)框架中专门设计用来与Reference(引用)抽象类配合使用的队列,采用链表的方式以实现。其作用是追踪引用的所指对象的GC状态,即判断所指对象是否已/会被GC回收。如果一个引用注册了引用队列,并且其所指对象被GC判定为可回收,则该引用会被加入到注册引用队列中(实际上这里只是简单叙述,将引用加入注册引用队列中其实是有相关运行流程的,这个运行流程被称为Reference(引用)机制,该知识点会在讲解引用抽象类的文章中详述)。这就意味着引用队列中的引用的所指对象必然已/会被GC回收,因此加入注册引用队列的引用可作为其所指对象已被GC回收的判断依据,开发者可以通过从注册引用队列中获取引用的方式来判断其对应的所指对象是否已/会被GC回收,并以此为契机执行某些自定义操作,例如回收堆外内存等。

    引用队列类的是无界队列,即容量理论上只受限于内容大小。

    引用队列类的本质是堆栈。虽然命名为队列,但引用队列的插入/移除操作都会在头部发生,因此引用队列类的本质是堆栈而非队列,这也就意味着引用的移除是非公平的,即后插入的引用反而会被先移除。

    引用队列类是线程安全的。引用队列类被用于多线程环境中,会被一条“引用处理器”线程及未知数量的用户线程共同访问,因此为了避免数据安全问题,其必须保证线程安全。引用队列类采用“单锁”线程安全机制,通过synchronized关键字来负责加锁,锁对象是其内部自实现的静态Null类对象…感觉完全没必要啊…用this不就可以了…

    引用队列类并不是Collection(集)框架的成员。虽说名为队列,但引用队列类并没有实现/继承Queue(队列)接口或集框架范围内的其它接口/抽象类/类,因此引用队列类并不是集框架的成员,是完全由引用框架自实现的。

 结构

在这里插入图片描述

二 使用


 创建

  • public ReferenceQueue() —— 创建引用队列。

 方法

  • public Reference<? extends T> poll() —— 轮询 —— 从当前引用队列的头部移除并获取引用。该方法是移除方法中“特殊值”形式的实现,当引用队列中存在引用时移除并返回头引用;否则返回null。

  • public Reference<? extends T> remove() throws InterruptedException —— 移除 —— 从当前引用队列的头部移除并获取引用。该方法是移除方法中“阻塞”形式的实现,当引用队列中存在引用时移除并返回头引用;否则等待至存在引用。该方法直接调用“超时”形式的移除方法实现,其传入的超时参数为0,表示无限等待。

  • public Reference<? extends T> remove(long timeout) throws IllegalArgumentException, InterruptedException —— 移除 —— 从当前引用队列的头部移除并获取引用。该方法是移除方法中“超时”形式的实现,当引用队列存在元素时移除并返回头引用;否则在指定等待时间内等待至存在引用,超出指定等待时间则返回null。当超时参数传0时表示无限等待。

    上述列举了引用队列类关于移除的所有方法,如果熟悉Queue(队列)/BlockingQueue(阻塞队列)接口定义的话会发现引用队列类在方法命名上与标准还是有所差异的(例如“阻塞”形式的实现在标准中被命名为take)。具体原因上文也已经提及,是因为引用队列类完全由引用架自实现,不是集框架成员的缘故。

    虽说已经列举了所有的移除方法,但我们似乎还遗漏了些什么…是的,我们没有列举插入方法。是因为没有吗?当然不可能,引用队列类是存在插入方法的,只是该方法并非公共方法,用户线程无法直接访问,理论上只有引用机制的“引用处理器”线程才会通过同包下的引用抽象类来调用该方法。具体如下:

  • boolean enqueue(Reference<? extends T> r) —— 入队 —— 从当前引用队列的头部插入指定引用,成功返回true;否则返回false。基于该方法“头插法”的实现方式可知引用队列类不是标准的FIFO实现,其本质是堆栈。

 模板

/**
 * 主方法
 *
 * @param args 参数集
 */
public static void main(String[] args) {
    // 创建引用队列。
    ReferenceQueue<Object> referenceQueue = new ReferenceQueue<>();
    // 以该引用队列为注册引用队列创建若引用及其所指对象。
    Object o1 = new Object();
    Object o2 = new Object();
    WeakReference<Object> weakReference = new WeakReference<>(o1, referenceQueue);
    PhantomReference<Object> phantomReference = new PhantomReference<>(o2, referenceQueue);
    // 断开程序对所指对象的强引用。
    o1 = null;
    o2 = null;
    // 主线程短暂等待1秒,确保JVM有充足的时间将引用加入引用队列中。
    LockSupport.parkNanos(1000000000);
    // 从引用队列中取出引用,从引用队列中取出的引用意味着其所指对象已/会被GC回收。
    Reference<?> reference;
    while ((reference = referenceQueue.poll()) != null) {
        System.out.println("引用【" + reference + "】的所指对象已/会被GC回收。");
    }
}

三 实现


 “空”引用队列与“入队”引用队列

    “空”引用队列与“入队”引用队列是引用队列类中创建的两个全局静态引用队列,是引用队列类的内部静态子类Null(空)类的对象,我们可以将之视为两个全局引用队列常量,虽然其并没有被修饰final关键字。空类重写了引用队列类的enqueue(Reference<? extends T> r)方法,令之固定返回false,意味着空类对象虽然是引用队列,但却永远都不会有引用入队。相关源码如下:

private static class Null<S> extends ReferenceQueue<S> {
    @Override
    boolean enqueue(Reference<? extends S> r) {
        // 入队操作直接返回false,意味着引用永远都不可能成功入队。
        return false;
    }
}

static ReferenceQueue<Object> NULL = new Null<>();
static ReferenceQueue<Object> ENQUEUED = new Null<>();

    “空”引用队列与“入队”引用队列分别被作为展示引用不同状态的标记值使用。引用存在状态的概念,用于表示其在引用机制中标的不同阶段,具体会在引用抽象类相关文章中详述。在这里我们只需要知道的是:“空”引用队列被作为引用未注册引用队列及引用已从注册引用队列出队的标记值。即当引用被创建时如果没有注册引用队列,则会将“空”引用队列作为默认注册引用队列(已知“空”引用队列是无法入队的)。以及如果引用已从注册引用队列中出队,则其注册引用队列也会被赋值为“空”引用队列。而对于如何区分引用是未注册引用队列还是已从注册引用中出队,则需要搭配引用中的其它条件综合判断,该知识点会在下文及引用抽象类相关文章中详述;而“入队”引用队列的作用则更加直观,被作为引用已加入注册引用队列的标志值,这一点从命名上就可以看出来…当引用于注册引用队列入队后,引用的注册引用队列会被赋值为“入队”引用队列。

 自引用

    引用队列会将尾引用/节点设置为自引用,即将尾引用/节点自身作为自身在引用队列中的后继引用/节点。尾节点在链表中的后继引用通常都为null,null本身既可以作为标记值也有助于GC。但有时如果基于流程的原因如果null已被作为其它情况的标记值,则自引用也是一种不错的替代方案。自引用不但可以作为标记值,并且在辅助GC中也有着不错的表现(虽然肯定是比不上null的)。

    引用队列之所以会将尾引用/节点设置为自引用与引用的状态有关。引用的后继引用与注册引用队列一样,都是状态的综合判断条件之一,而“空”引用队列与后继引用为null便是引用未注册引用队列的状态值。因此为了与其它状态值进行区分,引用在引用队列中的后继引用不可为null。

 终引用计数

    当引用队列发现入队/出队的引用为FinalReference(终引用)时,会对之进行计数,即对整个JVM(而不是某个引用队列)中的终引用总数进行递增/减。该操作的具体作用未知。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/634434.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

一篇就能学懂的散列表,让哈希表数据结构大放光彩

目录 1.散列表的基本概念 2.散列表的查找 3.散列函数的构造方法 1.直接定址法 2.除留余数法 4.散列表解决冲突的方法 1.开放定址法 2.链地址法 1.散列表的基本概念 基本思想&#xff1a;记录的存储位置与关键字之间存在的对应关系 对应关系——hash函数 Loc(i) H(k…

关于外包被开要怎么维护自己的权益

我一直以为外包被开都是没有任何赔偿的&#xff0c;之前网上对于外包的消息都是说&#xff0c;没有任何赔偿或者是怕麻烦然后就干脆放弃了的各种评论。。。但是最近我在问到一个朋友的时候&#xff0c;他很好的维护了自己的权益。最后获得了N1 保留证据 当被告知外包需要你离场…

牛客网语法篇刷题(C语言) — 运算

作者主页&#xff1a;paper jie的博客_CSDN博客-C语言,算法详解领域博主 本文作者&#xff1a;大家好&#xff0c;我是paper jie&#xff0c;感谢你阅读本文&#xff0c;欢迎一建三连哦。 本文录入于《C语言-语法篇》专栏&#xff0c;本专栏是针对于大学生&#xff0c;编程小白…

单链表OJ题:LeetCode--138.复制带随即指针的链表

朋友们、伙计们&#xff0c;我们又见面了&#xff0c;本期来给大家解读一下LeetCode中第138道单链表OJ题&#xff0c;如果看完之后对你有一定的启发&#xff0c;那么请留下你的三连&#xff0c;祝大家心想事成&#xff01; 数据结构与算法专栏&#xff1a;数据结构与算法 个 人…

python使用Faker库进行生成模拟mock数据(基本使用+五个小案例)

使用faker进行生成模拟(mock))数据 文章目录 使用faker进行生成模拟(mock))数据一、Faker库安装二、Faker库基本介绍三、案例1&#xff1a;Faker库生成核酸数据四、案例2&#xff1a;生成不重复的人名和地名五、案例3&#xff1a;生成有时间期限的低保数据六、案例4&#xff1a…

01-Vue 项目环境搭建和创建准备工作

一. 学习目标 掌握 Vue 项目创建的依赖环境掌握 Vue 项目创建过程 二. 学习内容 掌握搭建 Vue 项目准备环境掌握 Vue 项目创建过程了解 Vue 项目各子目录 三. 学习过程 1. 准备工作 &#xff08;1&#xff09;安装Node.js 打开node.js官网&#xff1a;Node.js &#xff0…

【状态估计】无迹卡尔曼滤波(UKF)应用于FitzHugh-Nagumo神经元动力学研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

详解ASP.NET Core 在 IIS 下的两种部署模式

KestrelServer最大的优势体现在它的跨平台的能力&#xff0c;如果ASP.NET CORE应用只需要部署在Windows环境下&#xff0c;IIS也是不错的选择。ASP.NET CORE应用针对IIS具有两种部署模式&#xff0c;它们都依赖于一个IIS针对ASP.NET CORE Core的扩展模块。 一、ASP.NET CORE C…

UML类图入门

UML类图入门 UML是一个通用的可视化建模描述语言&#xff0c;通过图形符号和文字来对系统进行建模。适用于各种软件的开发方法、生命周期的各个阶段。 类的UML图示 类使用包含类型、属性和操作&#xff08;方法&#xff09;且带有分割线的长方形来表示&#xff0c;如&#x…

人际关系的学习改进

表达的目的&#xff1a;让别人对你感兴趣 不要有苦劳而无功劳 爱的五种语言&#xff1a;表达爱的语言 人类存在的中心&#xff0c;是渴望和人亲近&#xff0c;被人所爱。婚姻即是被设计满足这种亲密关系和爱的需求的&#xff1b;把注意力集中在情绪健康所需的那片爱土上&…

【C++ 程序设计】第 4 章:运算符重载

目录 一、运算符重载的概念 &#xff08;1&#xff09;重载运算符的概念 ① 重载运算符的概念 ② 可重载的运算符 ③ 不可重载的运算符 ④ 运算符的优先级 &#xff08;2&#xff09;重载运算符为类的成员函数 &#xff08;3&#xff09;重载运算符为友元函数 &#…

【Linux】Docker部署镜像环境 (持续更新ing)

防火墙 1、查看防火墙状态 sudo systemctl status ufw 2、开启防火墙 sudo systemctl start ufw 3、关闭防火墙 sudo systemctl stop ufw 4、开机禁止开启防火墙 sudo systemctl disabled ufw 5、开启自启防火墙 sudo systemctl enabled ufw Elasticsearch 1、安装指定版本 比…

使用Pillow库轻松实现图像尺寸调整——>使每个图像具有相同的大小,方便模型处理和训练

在计算机视觉领域,对图像进行尺寸调整是一项非常常见的操作。在训练深度神经网络时,因为计算资源和内存限制的原因,我们通常需要将图像缩放到相同的尺寸。 在本文中,我们将介绍如何使用Python中的Pillow库对图像进行尺寸调整,并提供一个示例程序resize_images。 1. Pytho…

VulnHub靶场-Chronos

目录 0x01 声明&#xff1a; 0x02 简介&#xff1a; 0x03 环境准备&#xff1a; 0x04 信息收集&#xff1a; 1、主机发现 2、NMAP扫描 3、访问业务 4、目录探测 5、查看网页代码 0x05 渗透测试过程&#xff1a; 1、Burp Suite抓包 2、构造payload 测试是否可以外联…

CSS基础学习--5 background背景

一、介绍&#xff1a; CSS 背景属性用于定义HTML元素的背景。 CSS 属性定义背景效果: background-color 背景颜色background-image 背景图片background-repeatbackground-attachmentbackground-position 二、属性 2.1、background-color 属性定义了元素的背景颜色 <s…

根据word模板生成pdf文件

1、首先建一个word&#xff0c;插入一个表格&#xff0c;需要填充的值用${parame}代替 &#xff08;注意&#xff1a;这里的参数要和java实体类里面的参数对应起来&#xff0c;代码放在下面&#xff09; 2、制作完成后另存为xml格式 3、然后用文本编辑工具打开这个xml文件&…

CSS基础学习--6 CSS Text(文本)

一、文本颜色 color:red; 颜色属性被用来设置文字的颜色。 颜色是通过CSS最经常的指定&#xff1a; 十六进制值 - 如: &#xff03;FF0000一个RGB值 - 如: RGB(255,0,0)颜色的名称 - 如: red body {color:red;} h1 {color:#00ff00;} h2 {color:rgb(255,0,0);} 二、文本的…

【备战秋招】每日一题:4月18日美团春招:题面+题目思路 + C++/python/js/Go/java带注释

2023大厂笔试模拟练习网站&#xff08;含题解&#xff09; www.codefun2000.com 最近我们一直在将收集到的各种大厂笔试的解题思路还原成题目并制作数据&#xff0c;挂载到我们的OJ上&#xff0c;供大家学习交流&#xff0c;体会笔试难度。现已录入200道互联网大厂模拟练习题&a…

8 channel、反射、网络编程【Go语言教程】

8 channel、反射、网络编程【Go语言教程】 1 channel 1.1 概念及快速入门 channel:管道&#xff0c;主要用于不同goroutine之间的通讯 需求&#xff1a;现在要计算 1-200 的各个数的阶乘&#xff0c;并且把各个数的阶乘放入到 map 中。最后显示出来。要求使用 goroutine 完成…

[LeetCode周赛复盘] 第 349 场周赛20230611

[LeetCode周赛复盘] 第 349 场周赛20230611 一、本周周赛总结6470. 既不是最小值也不是最大值1. 题目描述2. 思路分析3. 代码实现 6465. 执行子串操作后的字典序最小字符串1. 题目描述2. 思路分析3. 代码实现 6449. 收集巧克力1. 题目描述2. 思路分析3. 代码实现 6473. 最大和…