持有引用java.lang.ref 和 WeakHashMap

Thinking in java P554

 

 

持有引用

如果想继续持有对某个对象的引用,希望以后能够反问到该对象,

但是也希望能够允许垃圾回收器是否它,这是就应该使用Reference

对象。这样,可以继续使用改对象,而再内存消耗完时允许是否它。

 

以Reference对象作为你和普通引用的媒介,另外,一定不能有

普通的引用指向那个兑现g.zheyang就能达到上述目的。

(普通的引用指没有经Reference对象包装过的引用)。

如果垃圾回收器发现某个兑现沟通过普通引用是可获得的,该

对象就不会被释放。

 

SoftReference, WeakReference 和 PhantomReference由强到若,

对应不同级别的"可获得性".Softreference用以是想内存

敏感的高速缓存。Weak reference是为实现个"规范映射"

而设计的,它部妨碍垃圾回收器回收映射的键或值。

规范映射中对象的实力可以在程序的多处被同时使用,

以节省存储空间。Phantomreference用以调度回收前

的清理工作,比Java终止机制更灵活。

 

 

class VeryBig {
	private static final int SIZE = 10000;
	private long[] la = new long[SIZE];
	private String ident;
	public VeryBig(String id){
		ident = id;
	}
	@Override
	public String toString() {
		return ident;
	}
	
	@Override
	protected void finalize() throws Throwable {
		System.out.println("Finalizing "+ident);
	}
}

public class References{
	private static ReferenceQueue<VeryBig> rq = 
		new ReferenceQueue<VeryBig>();

	public static void checkQueue(){
		Reference<? extends VeryBig> inq = rq.poll();
		if(inq != null)
			System.out.println("In Queue: "+inq.get());
	}
	
	public static void main(String[] args) {
		int size = 10;
		
		if(args.length > 0)
			size = new Integer(args[0]);
		LinkedList<SoftReference<VeryBig>> sa =
			new LinkedList<SoftReference<VeryBig>>();
		for(int i=0; i<size; i++){
			sa.add(new SoftReference<VeryBig>(
					new VeryBig("Soft "+ i), rq)
				);
			System.out.println("Just created: "+sa.getLast());
			checkQueue();
		}
		
		LinkedList<WeakReference<VeryBig>> wa =
			new LinkedList<WeakReference<VeryBig>>();
		for(int i=0; i<size; i++){
			wa.add(new WeakReference<VeryBig>(
					new VeryBig("Weak "+ i), rq)
			);
			System.out.println("Just created: "+wa.getLast());
			checkQueue();
		}
		
		SoftReference<VeryBig> s =
			new SoftReference<VeryBig>(new VeryBig("Soft"));
		
		WeakReference<VeryBig> w =
			new WeakReference<VeryBig>(new VeryBig("Weak"));
		
		System.gc();
		
		LinkedList<PhantomReference<VeryBig>> pa =
			new LinkedList<PhantomReference<VeryBig>>();
		for(int i=0; i<size; i++){
			pa.add(new PhantomReference<VeryBig>(
					new VeryBig("Phantom "+ i), rq)
			);
			System.out.println("Just created: "+pa.getLast());
			checkQueue();
		}
	}
}

 

结果

 

Just created: java.lang.ref.WeakReference@1d5550d

Just created: java.lang.ref.WeakReference@c2ea3f

Just created: java.lang.ref.WeakReference@a0dcd9

Just created: java.lang.ref.WeakReference@1034bb5

Just created: java.lang.ref.WeakReference@f9f9d8

Finalizing Weak 0

Finalizing Weak

Finalizing Weak 8

Finalizing Weak 7

Finalizing Weak 6

Finalizing Weak 5

Finalizing Weak 4

Finalizing Weak 3

Finalizing Weak 2

Finalizing Weak 1

Finalizing Weak 9

Just created: java.lang.ref.PhantomReference@112f614

In Queue: null

Just created: java.lang.ref.PhantomReference@1d9dc39

In Queue: null

Just created: java.lang.ref.PhantomReference@93dcd

In Queue: null

Just created: java.lang.ref.PhantomReference@b89838

In Queue: null

Just created: java.lang.ref.PhantomReference@111a3ac

In Queue: null

Just created: java.lang.ref.PhantomReference@dd20f6

In Queue: null

Just created: java.lang.ref.PhantomReference@723d7c

In Queue: null

Just created: java.lang.ref.PhantomReference@1d1acd3

In Queue: null

Just created: java.lang.ref.PhantomReference@8814e9

In Queue: null

Just created: java.lang.ref.PhantomReference@1503a3

In Queue: null


 

 

 

尽管还要通过Reference对象访问那些对象(使用get()取得实际的对象引用),

但是还是被垃圾回收器回收了。

可以看到,REferenceQueue总是生成一个包含null对象的Reference.

 

 

 

 

容器中WeakHashMap,用来保存WeakReference。每个值只保存一份实例

以节省存储空间,查值,则在映射中查询现有对象,然后使用它。

映射可将值作为其初始化一部分,不过通常是在需要的时候才生成值。

 

对于向WeakHashMap添加键和值的操作,没有什么特殊要求,映射会

自动使用WeakReference包装他们。允许清理元素的触发条件是,

不需要这个键。

 

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 r){
		return r instanceof Element && 
			ident.equals(((Element)r).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;
		if(args.length > 0)
			size = new Integer(args[0]);
		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();
	}
}

 

结果:

zing Key 209

Finalizing Key 208

Finalizing Key 206

Finalizing Key 205

Finalizing Key 203

Finalizing Key 202

Finalizing Key 200

Finalizing Key 199

Finalizing Key 197

Finalizing Key 196

Finalizing Key 194

Finalizing Key 193

Finalizing Key 191

Finalizing Key 190

Finalizing Key 188

...

可以看到垃圾回收期每隔三个键就跳过一个,因为指向那个键的普通引用被存如了Keys数组,

所以偶那些对象不能被垃圾回收器回收。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值