引用
软引用
- 软引用用于构建敏感数据的缓存,弱引用与软引用的区别仅是当前引用失效的时机不同,如果弱引用仅在GC即将OOM的时候
- 虚引用与软引用的区别:不会影响GC,但是需要强制使用ReferenceQueue,从而在回首的时候会是该引用进入队列中,是程序员知道该对象已经被回收
package com.demo;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
class LastIdxException extends Throwable {
public LastIdxException(String msg) {
super(msg);
}
}
class PerSon {
private int idx;
private String name;
public int getIdx() {
return idx;
}
public void setIdx(int idx) {
this.idx = idx;
}
public PerSon(int idx, String name) {
super();
this.idx = idx;
this.name = name;
}
public PerSon(PerSon p) {
super();
this.idx = p.idx;
this.name = p.name;
}
}
public class PersonVisitor {
// 模拟数据库中有10个Idx
PerSon[] perSonDB = new PerSon[10];
{
for (int i = 0; i < 10; i++) {
PerSon perSon = new PerSon(i, "名称" + i);
perSonDB[i] = perSon;
}
}
// 上一次读取的ID
int lastIdx = -1;
// 当前读取的ID
int currentIdx = -1;
// 上一次读取的对象缓存起来
WeakReference<PerSon> lastPerson;
PerSon currentPerson;
ReferenceQueue<PerSon> referenceQueue = new ReferenceQueue<>();
public void read(int idx) {
PerSon perSon = find(idx);
System.out.println(perSon.getIdx() + ":被查看");
if (currentIdx != -1) {
lastIdx = currentIdx;
lastPerson = null;//help gc
lastPerson = new WeakReference<PerSon>(currentPerson,referenceQueue);
}
currentIdx = idx;
currentPerson=perSon;
//PerSon perSon = perSonDB[idx];
}
private PerSon find(int idx) {
try {
Thread.sleep(30);
} catch (InterruptedException e) {
e.printStackTrace();
}
//利用new PerSon来模拟会创建很多对象
return new PerSon(perSonDB[idx]);
}
public void readLast() throws LastIdxException {
/**
* 如果设置缓存软引用则将此段注释
*/
if(lastPerson!=null&&lastPerson.get()!=null) {
PerSon perSon = (PerSon)lastPerson.get();
System.out.println(perSon.getIdx()+":被查看");
PerSon p = lastPerson.get();
lastPerson = new WeakReference<PerSon>(currentPerson,referenceQueue);
currentPerson = p;
return;
}
System.out.println("缓存已经失效");
Reference<? extends PerSon> poll = referenceQueue.poll();
System.out.println(lastPerson.get()==null);
if (lastIdx != -1)
read(lastIdx);
else {
throw new LastIdxException("last idx = -1");
}
}
public static void main(String[] args) {
long l=System.currentTimeMillis();
PersonVisitor visitor = new PersonVisitor();
visitor.read(3);
visitor.read(4);
try {
System.out.println("触发GC");
System.gc();
visitor.readLast();
visitor.readLast();
} catch (LastIdxException e) {
e.printStackTrace();
}
System.out.println("耗时:"+(System.currentTimeMillis()-l));
}
}
这里使用weakRefrence而没用SoftReference是因为这样更能够触发GC的回收软引用