说是原创吧,但是也是看别人的内容进行学习的,说不是原创吧,全部的代码是自己手敲了一遍,姑且认为是原创,会贴出所有参考过的帖子。
如果需要了解完整的原理,源码讲解,请查看以下的代码内容,博主讲的很详细了。
整理内容后心得和总结
内容提供给大家参考,如有不当请指出。尽量尽快修改
1、ReferenceQueue是检测被回收的内容的队列,请阅读上文的原理,便可得知,只有被回收的对象才会到此处
2、Reference是标记或者包装内容的对象
3、Reference的继承类有WeakReference(弱引用),软引用SoftReference,虚引用PhantomReference,保底引用FinalReference
4、强引用是默认,没有继承类
其中 保底引用FinalReference 是管理其他非自动释放的资源的(未尝试)
5、包装后的数据,按照正常的使用方式进行使用,按照gc的回收规则,引用的内容会进行具体的操作
6、正常的使用类,list,map之类的,使用上都是一样,不过需要提前判断当前的内容是否已经被回收掉了。
7、包装的过程Reference<包装对象类名称> ref = new WeakReference<包装对象类名称>( 包装对象内容, ReferenceQueue队列实例 );
8、检测是否被回收的内容 从ReferenceQueue队列实例中检测看内容是否还存在
while((reff=( Reference< char[] > ) queue.remove())!=null) {}
完整的代码如下:
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
public class CReferenceText
{
private static int sizeNum = 1024*1024;
public static void main( String[] args )
{
/**
* 定义获取内容的队列
* ReferenceQueue是检测被回收的内容
* Reference是标记的对象,
* Reference的继承类有WeakReference(弱引用),软引用SoftReference,虚引用PhantomReference,保底引用FinalReference
* @其中 保底引用FinalReference 是管理其他非自动释放的资源的
* 包装后的数据,按照正常的使用方式进行使用,按照gc的回收规则,引用的内容会进行具体的操作
* 正常的使用类,list,map之类的,使用上都是一样,不过需要提前判断当前的内容是否已经被回收掉了。
* 包装的过程Reference<包装对象类名称> ref = new WeakReference<包装对象类名称>( 包装对象内容, ReferenceQueue队列实例 );
* 检测是否被回收的内容 从ReferenceQueue队列实例中检测看内容是否还存在
* while((reff=( Reference< char[] > ) queue.remove())!=null)
*/
// map 内容测试
// mapTest();
// list 内容测试
listTest();
}
private static void listTest() {
ReferenceQueue< char[] > queue = new ReferenceQueue<char[] >();
List<Reference<char[]>> list = new ArrayList<>();
// 定义守护线程
Thread thread = new Thread(new Runnable()
{
@Override
public void run()
{
Reference<char[]> reff;
try
{
// 检测是否已经被回收了
while((reff=( Reference< char[] > ) queue.remove())!=null) {
System.out.println( "回收数据"+ reff );
}
}
catch ( InterruptedException e )
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
// 设置守护线程
thread.setDaemon( true );
thread.start();
for(int i=0;i<1000;i++) {
char[] c = new char[sizeNum];
// 封装或者转换或者包装对象,包装之后为指定内容的数据
Reference<char[]> ref = new WeakReference< char[] >( c, queue );
list.add( ref );
}
System.out.println( "内容写入完成,目前大小为:" + list.size() );
int liveNum = 0;
int len = list.size();
for(int i=0;i<len;i++) {
Reference<char[]> ref = list.get( i );
if(null != ref && null!=ref.get()) {
liveNum++;
}
}
System.out.println( "存活数量内容"+liveNum );
}
private static void mapTest() {
ReferenceQueue< char[] > queue = new ReferenceQueue<char[] >();
// 定义存储的map对象
Map<String,Reference<char[]>> map = new HashMap< String,Reference<char[]>>();
// 定义守护线程
Thread thread = new Thread(new Runnable()
{
@Override
public void run()
{
Reference<char[]> reff;
try
{
// 检测是否已经被回收了
while((reff=( Reference< char[] > ) queue.remove())!=null) {
System.out.println( "回收数据"+ reff );
}
}
catch ( InterruptedException e )
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
// 设置守护线程
thread.setDaemon( true );
thread.start();
// 定义持续性的增加加入内容
for(int i=0;i<1000;i++) {
String key = UUID.randomUUID().toString();
char[] c = new char[sizeNum];
// 封装或者转换或者包装对象,包装之后为指定内容的数据
Reference<char[] > ref = new WeakReference< char[] >( c, queue );
map.put( key ,ref );
}
System.out.println( "写入内容完成,目前map内容大小->" + map.size() );
int liveNum = 0;
for(Map.Entry<String,Reference<char[]>> entry:map.entrySet()) {
if(null!=entry && null!=entry.getKey() && null!=entry.getValue() && null!=entry.getValue().get()) {
liveNum++;
}
}
System.out.println( "存活个数->" + liveNum );
}
}