Android面试题目之(九) 幽灵引用

Android面试题目之(9) 幽灵引用

幽灵引用是android中最不会使用的引用,其作为finalize的替代方案,可以避免finalize的timeout。但是有时候并不是很好用,应为其发生在finalize之后,而这时候,这个对象已经不复存在。

这里的思想是,对象不能不存在,这个时候用另外一个对象去表示对这个对象的引用。

这样的话,对象就可以存在了,类似智能指针。

 

当然我们也可以用weakreference 做类似的事情,weakreference最大的问题是,weakreference.get()返回null的时候, 不一定 finalize()已经被调用,这个顺序很难确定。当然我们其实也不关心这个,只要我们能够收到finalize()或者将要finalize()的事件就可以了。

 

package sort;

import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;
import java.util.ArrayList;
import java.util.List;

import sort.Refer.ReferInfo;

public class Refer<T extends Releasable> {
private static ReferenceQueue<Refer<? extends Releasable>> queue = new ReferenceQueue<>();
	public static class ReferInfo<T extends Releasable> {

		private T t;
		
		

		private PhantomReference<Refer<? extends Releasable>> phantomRef = null;
	}
	
	private T t;

	private static List<ReferInfo<Releasable>> mInfos = new ArrayList<>();

	static {
		start();
	}
	
	public static void start() {
		new Thread(new Runnable() {
			public void run() {
				while (true) {
					synchronized (mInfos) {
                                  queued = key.queue.remove(Integer.Max);
                                  if (queued  != null) {
						for (ReferInfo<?> key : mInfos) {
							//TODO:
                                                          if(key.phantomRef == queued){
								System.out.println("enqueued!");
								key.t.release();
							  }
							mInfos.remove(key);
							break;
						}
                                              }
					}
					try {
						Thread.sleep(100);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					System.gc();

				}
			}
		}).start();
	}

	public Refer(T t) {
		this.t = t;
		ReferInfo<Releasable> info = new ReferInfo<>();
		info.phantomRef = new PhantomReference<>(this, queue);
		info.t = t;
		synchronized (mInfos) {
			mInfos.add(info);
		}
	}

	@Override
	protected void finalize() throws Throwable {
		super.finalize();
		System.out.println("finalize");
	}
}

  下面是一个releasable

   

package sort;

public interface Releasable {

	void release();
}

 下面是一个使用方法:

  

package sort;

import java.lang.ref.PhantomReference;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;

public class PhantomreferenceStudy implements Releasable {

	public static void main(String[] args) throws InterruptedException {
		System.out.println(".....");
		Refer refer = new Refer(new PhantomreferenceStudy());
		refer = null;
		while (true) {
			System.gc();
		}
	}
	
	@Override
	public void release() {
	        //在这里做一些清理的工作。而不是finalize, 这个方法发生在finalize之前。
	}
}

 打印:

   

.....
finalize
enqueued!

 完毕