强、软、弱、虚四大引用示例
一、强引用
我们日常使用的都是强引用
,如下:
StringBuffer str = new StringBuffer("Hello World")
强引用的特点:
- 强引用可以直接访问目标对象
- 强引用所指向的对象在任何时候都不会被垃圾回收,虚拟机宁愿报OOM,也不会回收强引用所指向的对象
- 强引用可能会导致内存泄漏
二、弱引用
特点:
- 当堆空间不足时,就会被回收
使用示例
/**
* 虚拟机参数:-Xmx10m
* 软引用配合引用队列使用,自动入队;也可以不配合引用队列使用
* @Author Helius
* @Create 2020-08-08-6:32 下午
*/
public class SoftRefQ {
public static class User {
int id;
String name;
public User(int id, String name) {
this.id = id;
this.name = name;
}
@Override
public String toString() {
return "[id = " + id + ", name = " + name + "]";
}
}
static ReferenceQueue<User> softQueue = null;
public static class CheckRefQueue extends Thread{
@Override
public void run() {
while (true) {
if (softQueue != null) {
UserSoftReference obj = null;
try {
obj =(UserSoftReference) softQueue.remove();
} catch (InterruptedException e) {
e.printStackTrace();
}
if (obj != null) {
System.out.println("user id " + obj.uid + " is delete");
}
}
}
}
}
public static class UserSoftReference extends SoftReference<User> {
int uid;
public UserSoftReference(User referent, ReferenceQueue<? super User> q) {
super(referent, q);
this.uid = referent.id;
}
}
public static void main(String[] args) throws InterruptedException {
Thread t = new CheckRefQueue();
t.setDaemon(true);
t.start();
User u = new User(1,"mary");
softQueue = new ReferenceQueue<>();
UserSoftReference userSoftReference = new UserSoftReference(u, softQueue);
u = null;
System.out.println(userSoftReference.get());
System.gc();
System.out.println("After GC");
System.out.println(userSoftReference.get());
System.out.println("try to create byte array and GC");
byte[] b = new byte[1024 * 925 * 7];
System.gc();
System.out.println(userSoftReference.get());
Thread.sleep(1000);
}
}
三、弱引用
特点
只要有GC
就会被回收,一般配合引用队列使用。
非常使用用来保持可有可无的缓存数据
使用示例:
public class WeakRef {
public static class User {
int id;
String name;
public User(int id, String name) {
this.id = id;
this.name = name;
}
@Override
public String toString() {
return "[id = " + id + ", name = " + name + "]";
}
}
public static void main(String[] args) {
User u = new User(1,"mary");
WeakReference<User> userWeakRef = new WeakReference<>(u);
u = null;
System.out.println(userWeakRef.get());
System.gc();
//不管当前内存空间足够与否,都会回收它的内存
System.out.println("After GC:");
System.out.println(userWeakRef.get());
}
}
输出:
[id = 1, name = mary]
After GC:
null
四、虚引用
一个持有虚引用 的对象,和没有引用几乎是一样的,随时可能被垃圾器回收,当试图通过虚引用get()方法取得强引用时,总是会失败。
一般和引用队列一起使用,
使用示例:
public class TraceCanReliveObj {
public static TraceCanReliveObj obj;
static ReferenceQueue<TraceCanReliveObj> phantomQueue = null;
public static class CheckRefQueue extends Thread {
@Override
public void run() {
while (true) {
if (phantomQueue != null) {
PhantomReference<TraceCanReliveObj> objt = null;
try {
objt = (PhantomReference<TraceCanReliveObj>) phantomQueue.remove();
} catch (InterruptedException e) {
e.printStackTrace();
}
if (objt != null) {
System.out.println("TraceCanReliveObj is delete");
}
}
}
}
}
@Override
protected void finalize() throws Throwable {
super.finalize();
System.out.println("CanReliveObj finalize called");
obj = this;
}
@Override
public String toString() {
return "I am CanReliveObj";
}
public static void main(String[] args) throws InterruptedException {
Thread t = new CheckRefQueue();
t.setDaemon(true);
t.start();
phantomQueue = new ReferenceQueue<>();
obj = new TraceCanReliveObj();
//构造虚引用
PhantomReference<TraceCanReliveObj> phantomRef = new PhantomReference<>(obj,phantomQueue);
obj = null;
System.gc();
Thread.sleep(1000);
if (obj == null) {
System.out.println("obj is null");
} else {
System.out.println("obj 可用");
}
System.out.println("第2次 GC");
obj = null;
System.gc();
Thread.sleep(1000);
if (obj == null) {
System.out.println("obj is null");
} else {
System.out.println("obj 可用");
}
}
}
输出:
CanReliveObj finalize called
obj 可用
第2次 GC
TraceCanReliveObj is delete
obj is null
五、小结:
应付面试尔。
你所看得到的天才不过是在你看不到的时候还在努力罢了!