一、java中有哪几种引用,他们的含义和区别是什么?
强引用、软引用、弱引用、虚引用
含义
强引用(StrongReference) 是使用最普遍的引用。如果一个对象具有强引用,那垃圾回收器绝不会回收它。当内存空间不足,java宁愿抛出OutOfMemoryError 的错误使程序异常终止,也不会考随意回收具有强引用的对象来解决内存不足的问题。
强引用的写法如下:
Object o = new Object();
String str = "123";
如果出现以下情况:
A a = new A();
B b = new B(a);
a = null;
这个时候 a 是对象A 的引用,b是对象B的引用,同时B依赖于A。如果这个时候用a = null去回收对象是不可以的,因为此时a仍被b持有,A的对象不能被回收,B还依赖于A,就会造成内存泄漏。
所当然如果你不想让正在使用的对象被回收,就选择强引用。如果像上面代码一样想要回收,不妨换其他的引用方式。
软引用(SoftReference ) 是用来描述一些有用但是并不是必需的对象,只有在内存不足的时候JVM才会回收改对象。所以这种引用可以很好的解决OOM的问题,并且这个特性比较适合用来实现缓存:例如图片缓存,网页缓存等等。
引用写法:
SoftReference<String> sr = new SoftReference<String>(new String("hello Android"));
弱引用(WeakReference)垃圾回收时,无论内存是否充足,都会回收弱引用相关联的对象。
弱引用可以和一个引用队列(ReferenceQueue)联合使用,如果弱引用所引用的对象被垃圾回收,java虚拟机就会把这个弱引用加入到与之关联的引用队列中。
引用写法:
WeakReference<String> sr = new WeakReference<String>(new String("hello"));
虚引用(PhantomReference)和前面的软引用、弱引用不同,它最大的区别就是不影响对象的生命周期。如果一个对象用虚引用的方式关联使用,则跟没有引用关联一样,在任何时候都有可能被来及回收器回收。
虚引用必须和引用队列关联使用,当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会把这个虚引用假如到与之关联的引用队列中。程序可以通过判断引用队列中是否加入了虚引用来了解被引用的对象是否将要被垃圾回收。
引用写法:
ReferenceQueue queue = new ReferenceQueue ();
PhantomReference pr = new PhantomReference (object, queue);
区别
(1)强引用:无论内存是否足够,都不会被回收
(2)软引用:内存不足的时候,会回收该引用关联的对象
(3)弱引用:垃圾回收时,无论内存是否充足,都会被回收
(4)虚引用:任何时候都可能被垃圾回收机制回收
二、请用java实现一个线程安全且高效的单例模式。
线程安全是指多线程访问时,采用了加锁机制,当一个线程访问该类的某个数据是,进行保护,其他线程不能进行访问知道改线程读取完,其他线程才可以使用。不会出现数据不一致或者数据污染。
public class Singleton {
private volatile static Singleton uniqueInstance;
private Singleton() {}
public static synchronized Singleton getInstance() {
if(uniqueInstance == null) {//(1)
//只有第一次才彻底执行这里的代码
synchronized() {
//再检查一次
if(uniqueInstance == null)
uniqueInstance = new Singleton();
}
}
return uniqueInstance;
}
}
首先必须要添加一个私有的无参构造方法,用来限制外界获取对象途径只能通过getInstance(); 另外采取synchronized,迫使每个线程在进入方法之前,要先等别的线程离开该方法。也就是说,不会有两个线程可以同时进入这个方法。