java ref 应用类型_Java四种引用类型

Java四种引用类型

在java中,类型就分为两种,基本类型和引用类型或自定义类型。

引用类型又分为四种:

强引用 StrongReference

软引用 SoftReference

若引用 WeakReference

虚引用 PhantomReference

划分这些类型的目的是:是为了更灵活的管理对象的生命周期,让垃圾器在最合适的时间适合回收对象,常见使用的场景是在缓存的实现,比如elasticsearch在载入数据到缓存时,可以选择SoftReference作为缓存的生命周期,在对象池组件common-pool中也利用到SoftReference管理对象池的对象生命周期。虽然,我们在实际业务中很少有用到这些知识,但是很有必要了解到这些,去帮助我们去做些程序性能优化。

强引用

强引用就是直接引用对象比如下面这样,我们在编写程序时,用到的大多都是强引用

StringBuffer b1 = new StringBuffer("hello world");

强引用对象,当垃圾回收进行时,不会被回收,及时通过b1 = null;释放引用,在资源充足时,也不会被垃圾回收立刻回收。如果内存吃紧,Java虚拟机会抛出OutOfMemoryError错误,使程序异常终止,不会靠随意回收具有强引用的对象来解决内存不足的问题。

软引用

SoftReference softReference = new SoftReference(new StringBuffer("hello world"));

System.gc();

System.out.print(softReference.get()); // 只有当内存吃紧时,发生gc后,会报Exception in thread "main" java.lang.NullPointerException,

软引用的生命周期会比强引用弱点,在内存空间足够时,垃圾回收器就不会回收它;如果内存空间不足了,就会回收这些对象的内存。只要垃圾回收器没有回收它,该对象就可以被程序使用。软引用可用来实现内存敏感的高速缓存。

它也经常和ReferenceQueue配合使用,如果gc在回收掉引用对象后,会把保存引用对象的softReference送入队列,这时可以通过下面这行代码判断是否被回收。

// 创建softReference并提供给注册队列

ReferenceQueue referenceQueue = new ReferenceQueue();

SoftReference softReference = new SoftReference(new StringBuffer("hello world"),referenceQueue);

// 判断入队列来判断是否被回收,或直接判断softReference.get() == null

softReference.get() == null || softReference.enqueue()

另外也可以手动清除这些保存引用对象的reference对象

Reference ref;

while ((ref = referenceQueue.poll()) != null) {

// poll出即清除,也不必手动清除,等待gc清除

}

使用案列:common-pool2的SoftReferenceObjectPool,用于实现一种可以随着需要而增长的池对象管理,当gc时可以清除空闲的实例。

下面是common-pool2的部分代码,具体可以参照其里面的SoftReferenceObjectPool类

@Override

public synchronized void addObject() throws Exception {

assertOpen();

if (factory == null) {

throw new IllegalStateException(

"Cannot add objects without a factory.");

}

T obj = factory.makeObject().getObject();

createCount++;

// Create and register with the queue

PooledSoftReference ref = new PooledSoftReference(

new SoftReference(obj, refQueue));

allReferences.add(ref);

boolean success = true;

if (!factory.validateObject(ref)) {

success = false;

} else {

factory.passivateObject(ref);

}

boolean shouldDestroy = !success;

if (success) {

idleReferences.add(ref);

notifyAll(); // numActive has changed

}

if (shouldDestroy) {

try {

destroy(ref);

} catch (Exception e) {

// ignored

}

}

@Override

public synchronized void returnObject(T obj) throws Exception {

boolean success = !isClosed();

final PooledSoftReference ref = findReference(obj);

if (ref == null) {

throw new IllegalStateException(

"Returned object not currently part of this pool");

}

if (factory != null) {

if (!factory.validateObject(ref)) {

success = false;

} else {

try {

factory.passivateObject(ref);

} catch (Exception e) {

success = false;

}

}

}

boolean shouldDestroy = !success;

numActive--;

if (success) {

// Deallocate and add to the idle instance pool

ref.deallocate();

idleReferences.add(ref);

}

notifyAll(); // numActive has changed

if (shouldDestroy && factory != null) {

try {

destroy(ref);

} catch (Exception e) {

// ignored

}

}

}

弱引用

WeakReference weakReference = new WeakReference(new StringBuffer("hello world"));

WeakReference weakReference2 = new WeakReference(new StringBuffer("hello world"));

System.out.print(weakReference.get()); // hello world

StringBuffer buffer = weakReference2.get();

System.gc();

System.out.print(weakReference.get()); // Exception in thread "main" java.lang.NullPointerException

System.out.print(weakReference2.get()); // hello world

弱引用会在发生gc时,没有对象在去引用时会被立刻被回收,不管内存是否充裕。

使用案列:WeakHashMap

虚引用

ReferenceQueue stringBufferReferenceQueue = new ReferenceQueue();

PhantomReference phantomReference = new PhantomReference(new StringBuffer("hello world"), stringBufferReferenceQueue);

System.out.print(phantomReference.get());Exception in thread "main" java.lang.NullPointerException

虚引用,不顾是否被垃圾回收,都不可以拿到真正的引用对象。一般用法是

程序可以通过判断引用队列中是否已经加入了虚引用,来了解被引用的对象是否将要被垃圾回收。如果程序发现某个虚引用已经被加入到引用队列,那么就可以在所引用的对象的内存被回收之前采取必要的行动。

具体Demo代码请参照:ReferenceDemo

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

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

相关文章

嵌入式Linux学习笔记

一 嵌入式系统定义: 应用于特定环境的硬件体系。 二 两样非常重要的能力: 1. 掌握各种新概念的能力 2. 调试的能力( 包括软件, 硬件 ) 三 需要的基础知识: 1. 操作系统理论基础 2. 数据结构 3. C,C编程语言 4. 汇编语言 5. Linux基…

java string 内存占用_JVM系列之:String,数组和集合类的内存占用大小

简介之前的文章中,我们使用JOL工具简单的分析过String,数组和集合类的内存占用情况,这里再做一次更详细的分析和介绍,希望大家后面再遇到OOM问题的时候不再抱头痛哭,而是可以有章可循,开始吧。数组先看下JOL的代码和输…

maven osgi_OSGi将Maven与Equinox结合使用

maven osgi很长时间以来,我一直在努力理解OSGi的真正含义。 它已经存在很长时间了,但是没有多少人意识到这一点。 它被炒作是一种非常复杂的技术。 这是我为所有Java开发人员简化的尝试。 简而言之, OSGi是一组规范,这些规范支持模…

java用redis缓存的步骤_详解在Java程序中运用Redis缓存对象的方法|chu

这段时间一直有人问如何在Redis中缓存Java中的List 集合数据,其实很简单,常用的方式有两种:1. 利用序列化,把对象序列化成二进制格式,Redis 提供了 相关API方法存储二进制,取数据时再反序列化回来&#xff…

Linux安装、卸载软件

在linux环境中,尤其是cenos中安装过一些软件,一般是二进制安装与源码安装,现小结一下linux中的安装与卸载。 一、通常Linux应用软件的安装包有三种: 1) tar包,如software-1.2.3-1.tar.gz。它是使用UNIX系统的打包工具t…

java绘制_Java 绘制简单图形的问题

代码能运行成功但东西出不来能帮忙看下代码吗?.O_O.importjava.awt.Color;importjava.awt.Graphics2D;importjavax.swing.JComponent;importjavax.swing.JFrame;importjava.awt.geom....代码 能运行成功 但东西出不来 能帮忙看下代码吗?.O_O.import java…

SonarQube中的Maven项目的单元和集成测试报告

自SonarQube 4.2起。 测试报告不是在Maven构建期间由Sonar Maven插件生成的(请参阅SonarQube的博客文章 )。 因此,在Sonar Maven插件收集SonarQube服务器的信息之前,必须由另一个插件生成测试报告。 在这里,Jacoco Mav…

IOS-状态栏的简单操作

一、启动时隐藏状态栏 1、在info.plist里面 Status bar is initially hidden 设置为 YES2、在appDelagate里面 设置 [application setStatusBarHidden:NO withAnimation:UIStatusBarAnimationFade]; 二、将所有页面状态栏字体颜色设为白色1.在info.plist中添加一个字段&#x…

python中、文件最重要的功能是( )和接收数据_Python基础语法14个知识点大串讲

来源:Python数据之道Python基础语法大串讲Python 是一门面向对象的编程语言,相信这篇文章对于初学者而言应该会有一个比较大的帮助,下面我们将 Python 中常用的基础语法和函数做了一个汇总,满满的干货,供大家学习。1、…

hadoop简单介绍_Hadoop:简单介绍

hadoop简单介绍什么是Hadoop: Hadoop是用Java编写的框架,用于在大型商品硬件群集上运行应用程序,并具有类似于Google File System和MapReduce的功能 。 HDFS是一个高度容错的分布式文件系统,与Hadoop一样,旨在部署在低…

SQL预编译防注入小测试

个人对SQL预编译的认识: 1、效率提升,对SQL语句编译一次可多次使用.避免了硬解析和软解析等步骤,当执行的语句上规模的时候性能差异还是很明显的。 2、安全提升,预编译之后的SQL语句,语义不会发生变化,安全性有相当大的提升。 using System; using System.Collectio…

春天:注入列表,地图,可选对象和getBeansOfType()陷阱

如果您使用Spring框架超过一个星期,那么您可能已经知道此功能。 假设您有多个bean实现了给定的接口。 尝试仅自动接线此类接口的一个bean注定会失败,因为Spring不知道您需要哪个特定实例。 您可以通过使用Primary批注来指定一个优先于其他实现的“ 最重要…

python实现表格分析与建模_python实现数据分析与建模

前言首先我们做数据分析,想要得出最科学,最真实的结论,必须要有好的数据。而实际上我们一般面对的的都是复杂,多变的数据,所以必须要有强大的数据处理能力,接下来,我从我们面临的最真实的情况&a…

Unity 利用Coroutine实现跳动数字效果

纯粹转载:转载注明参考链接! 参考链接:http://xataxnova.blog.163.com/blog/static/236620063201451061738122/,作者:网易博客 xataxnova 示例代码:(将该脚本绑在一个Lable对象上,即…

java mvc 案例_springmvc经典案例

本想自己写一下总结,但是发现一篇好文,转发一下,日后自己再做补充;感谢Sunnier,引自:https://www.cnblogs.com/sunniest/p/4555801.htmlSpringMVC学习笔记----一、SpringMVC基础入门,创建一个He…

Ajax.ActionLink 辅助方法实现局部刷新

1,需要引用一个JS文件jquery.unobtrusive-ajax.min.js【MVC4 默认存在Scripts文件夹里】引用到母版页 _Layout.cshtml,并且一定要放在JQuery引用文件之后 2,需要添加一个分布视图到指定的目录里,分布视图是用来显示局部刷新的 3&a…

java 命名约定_Java命名约定

java 命名约定我想写这篇简短的文章来帮助某些难以记住Java API类和方法名称的人。 如您所知,Java是区分大小写的语言,要构建Java程序,您需要使用许多内置API类和方法。 而且,初学者发现很难准确地记住方法名称和类名称而不改变大…

Discuz UCenter 修改手记 - 2014.12.19

最近在整JAVA和UCENTER的东西,受限于项目架构需要,无法完全以UCENTER为中心,所以在对接过程中遇到了许多不愉快的事情。经历多番研究,终于解决了其中了两个大问题,现记录下来,以备日后查看。 一、解决email…

java泛型方法无参_从头再来:Java泛型(开发必须知道的)

Java泛型老规矩,测试一下,下面的程序能否正常运行?为什么?开头测试题泛型就是实现了参数化类型,也就是代码可以适用于多种类型。泛型是在编译期检查的,在编译期检查类型是否安全。我认为泛型最有用的就是和…

几种常见模式识别算法整理和总结

这学期选了门模式识别的课。发现最常见的一种情况就是,书上写的老师ppt上写的都看不懂,然后绕了一大圈去自己查资料理解,回头看看发现,Ah-ha,原来本质的原理那么简单,自己一開始仅仅只是被那些看似formidab…