1
.对象的强、软、弱和虚引用
![](https://i-blog.csdnimg.cn/blog_migrate/8cc0cc28bc73d026eff53222ce5a0e29.jpeg)
ReferenceQueue
queue
=
new
ReferenceQueue ();
PhantomReference
pr
=
new
PhantomReference (
object
,
queue
);
|
![](https://i-blog.csdnimg.cn/blog_migrate/58f2beee524a808f057d1d240ff7abb8.jpeg)
MyObject
aRef
=
new
MyObject();
SoftReference
aSoftRef
=
new
SoftReference(
aRef
);
|
aRef
=
null
;
|
MyObject
anotherRef
=(MyObject)
aSoftRef
.get();
|
ReferenceQueue
queue
=
new
ReferenceQueue();
SoftReference
ref
=
new
SoftReference(
aMyObject
,
queue
);
|
SoftReference ref =
null
;
while
((ref = (EmployeeRef)
q
.poll()) !=
null
) {
//
清除
ref
}
|
public
class
Employee {
private
String
id
;
//
雇员的标识号码
private
String
name
;
//
雇员姓名
private
String
department
;
//
该雇员所在部门
private
String
Phone
;
//
该雇员联系电话
private
int
salary
;
//
该雇员薪资
private
String
origin
;
//
该雇员信息的来源
//
构造方法
public
Employee(String id) {
this
.
id
= id;
getDataFromlnfoCenter();
}
//
到数据库中取得雇员信息
private
void
getDataFromlnfoCenter() {
//
和数据库建立连接井查询该雇员的信息,将查询结果赋值
//
给
name
,
department
,
plone
,
salary
等变量
//
同时将
origin
赋值为
"From DataBase"
}
……
|
import
java.lang.ref.ReferenceQueue;
import
java.lang.ref.SoftReference;
import
java.util.Hashtable;
public
class
EmployeeCache {
static
private
EmployeeCache
cache
;
//
一个
Cache
实例
private
Hashtable<String,EmployeeRef>
employeeRefs
;
//
用于
Chche
内容的存储
private
ReferenceQueue<Employee>
q
;
//
垃圾
Reference
的队列
//
继承
SoftReference
,使得每一个实例都具有可识别的标识。
//
并且该标识与其在
HashMap
内的
key
相同。
private
class
EmployeeRef
extends
SoftReference<Employee> {
private
String
_key
=
""
;
public
EmployeeRef(Employee em, ReferenceQueue<Employee> q) {
super
(em, q);
_key
= em.getID();
}
}
//
构建一个缓存器实例
private
EmployeeCache() {
employeeRefs
=
new
Hashtable<String,EmployeeRef>();
q
=
new
ReferenceQueue<Employee>();
}
//
取得缓存器实例
public
static
EmployeeCache getInstance() {
if
(
cache
==
null
) {
cache
=
new
EmployeeCache();
}
return
cache
;
}
//
以软引用的方式对一个
Employee
对象的实例进行引用并保存该引用
private
void
cacheEmployee(Employee em) {
cleanCache();
//
清除垃圾引用
EmployeeRef ref =
new
EmployeeRef(em,
q
);
employeeRefs
.put(em.getID(), ref);
}
//
依据所指定的
ID
号,重新获取相应
Employee
对象的实例
public
Employee getEmployee(String ID) {
Employee em =
null
;
//
缓存中是否有该
Employee
实例的软引用,如果有,从软引用中取得。
if
(
employeeRefs
.containsKey(ID)) {
EmployeeRef ref = (EmployeeRef)
employeeRefs
.get(ID);
em = (Employee) ref.get();
}
//
如果没有软引用,或者从软引用中得到的实例是
null
,重新构建一个实例,
//
并保存对这个新建实例的软引用
if
(em ==
null
) {
em =
new
Employee(ID);
System.
out
.println(
"Retrieve From EmployeeInfoCenter. ID="
+ ID);
this
.cacheEmployee(em);
}
return
em;
}
//
清除那些所软引用的
Employee
对象已经被回收的
EmployeeRef
对象
private
void
cleanCache() {
EmployeeRef ref =
null
;
while
((ref = (EmployeeRef)
q
.poll()) !=
null
) {
employeeRefs
.remove(ref.
_key
);
}
}
//
清除
Cache
内的全部内容
public
void
clearCache() {
cleanCache();
employeeRefs
.clear();
System.
gc();
System.
runFinalization();
}
}
|
public
class
SocketManager {
private
Map<Socket, User>
m
=
new
HashMap<Socket, User>();
public
void
setUser(Socket s, User u) {
m
.put(s, u);
}
public
User getUser(Socket s) {
return
m
.get(s);
}
public
void
removeUser(Socket s) {
m
.remove(s);
}
}
|
import
java.util.WeakHashMap;
class
Element {
private
String
ident
;
public
Element(String id) {
ident
= id;
}
public
String toString() {
return
ident
;
}
public
int
hashCode() {
return
ident
.hashCode();
}
public
boolean
equals(Object obj) {
return
obj
instanceof
Element &&
ident
.equals(((Element) obj).
ident
);
}
protected
void
finalize(){
System.
out
.println(
"Finalizing "
+getClass().getSimpleName()+
" "
+
ident
);
}
}
class
Key
extends
Element{
public
Key(String id){
super
(id);
}
}
class
Value
extends
Element{
public
Value (String id){
super
(id);
}
}
public
class
CanonicalMapping {
public
static
void
main(String[] args){
int
size=1000;
Key[] keys=
new
Key[size];
WeakHashMap<Key,Value> map=
new
WeakHashMap<Key,Value>();
for
(
int
i=0;i<size;i++){
Key k=
new
Key(Integer.toString(i));
Value v=
new
Value(Integer.toString(i));
if
(i%3==0)
keys[i]=k;
map.put(k, v);
}
System.
gc();
}
}
|
public
class
SocketManager {
private
Map<Socket,User>
m
=
new
WeakHashMap<Socket,User>();
public
void
setUser(Socket s, User u) {
m
.put(s, u);
}
public
User getUser(Socket s) {
return
m
.get(s);
}
}
|
5 虚引用(PhantomReference)
"虚引用"顾名思义,就是形同虚设,与其他几种引用都不同,虚引用并不会决定对象的生命周期。如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收。虚引用主要用来跟踪对象被垃圾回收的活动。
虚引用与软引用和弱引用的一个区别在于:虚引用必须和引用队列(ReferenceQueue)联合使用。当垃 圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到与之关联的引用队列中。程序可以通过判断引用队列中是 否已经加入了虚引用,来了解被引用的对象是否将要被垃圾回收。程序如果发现某个虚引用已经被加入到引用队列,那么就可以在所引用的对象的内存被回收之前采取必要的行动。
建立虚引用之后通过get方法返回结果始终为null,通过源代码你会发现,虚引用通向会把引用的对象写进referent,只是get方法返回结果为null.先看一下和gc交互的过程在说一下他的作用.
1 不把referent设置为null, 直接把heap中的new String("abc")对象设置为可结束的(finalizable).
2 与软引用和弱引用不同, 先把PhantomRefrence对象添加到它的ReferenceQueue中.然后在释放虚可及的对象.
你会发现在收集heap中的new String("abc")对象之前,你就可以做一些其他的事情.通过以下代码可以了解他的作用.
import java.lang.ref.PhantomReference;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.reflect.Field;
public class Test {
public static boolean isRun = true;
public static void main(String[] args) throws Exception {
String abc = new String("abc");
System.out.println(abc.getClass() + "@" + abc.hashCode());
final ReferenceQueue referenceQueue = new ReferenceQueue<String>();
new Thread() {
public void run() {
while (isRun) {
Object o = referenceQueue.poll();
if (o != null) {
try {
Field rereferent = Reference.class
.getDeclaredField("referent");
rereferent.setAccessible(true);
Object result = rereferent.get(o);
System.out.println("gc will collect:"
+ result.getClass() + "@"
+ result.hashCode());
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}.start();
PhantomReference<String> abcWeakRef = new PhantomReference<String>(abc,
referenceQueue);
abc = null;
Thread.currentThread().sleep(3000);
System.out.println("++++++++++++++++++++++++++++++++++++");
System.gc();
Thread.currentThread().sleep(3000);
System.out.println("========================");
isRun = false;
}
}
执行结果:
class java.lang.String@96354
++++++++++++++++++++++++++++++++++++
gc will collect:class java.lang.String@96354
========================