注意(实现单例模式有以下几个关键点):
(a)函数构造器不对外开放,为私有的(private);
(b)在类里,通过一个静态的方法或者枚举返回该类的单例对象;
(c)保证类的单例对象有且只有一个(尤其在多线程的情况下);
(d)在反序列化时,保证类的单例对象不会被重新构建。
第一种:懒汉模式
public final class LazySingleton { private static LazySingleton mInstance; private LazySingleton() { } /** * 加入了同步, 在多线程下, 保证了单例对象的唯一性 * * @return 返回单例对象 */ public static synchronized LazySingleton getInstance() { if (mInstance == null) { mInstance = new LazySingleton(); } return mInstance; } }优点:在使用到时 ,才被实例化 ,在一定程度上了 ,省下了资源。
缺点:第一次去加载时,需要直接进行实例化,反应会稍微有点慢,每次调用都需要同步,从而会造成不必要的同步开销。
所以,不强烈推荐使用这种模式。
第二种:DCL(Double Check Lock) 来实现单例
public final class LazySingleton { private volatile static LazySingleton mInstance = null; private LazySingleton() { } /** * 双重判断(第一重:为了避免不必要的同步;第二重:在为null的时,new一个实例) * * @return 返回单例对象 */ public static LazySingleton getInstance() { if (mInstance == null) { synchronized (LazySingleton.class) { if (mInstance == null) { mInstance = new LazySingleton(); } } } return mInstance; } }
优点:能够在需要时才进行初始化,又能够保证线程安全,而且调用方法不进行同步锁,资源利用率高,效率也高。
缺点:第一次加载反应稍微慢,由于Java内存模型原因偶尔会失效。
所以,可以推荐使用这种模式。
第三种:静态内部类单例模式
public final class LazySingleton { private LazySingleton() { } public static LazySingleton getInstance() { return LazySingletonHolder.mInstance; } private static class LazySingletonHolder { private static final LazySingleton mInstance = new LazySingleton(); } }总结:第一次加载时不会初始化mInstance,只有在第一次调用getInstacne()时才会被初始化,因此,不仅保证了线程安全,也保证了单例对象的唯一性,也延迟了单例的实例化,所以,推荐使用这种单例模式。
第四种:枚举单例模式
public enum LazySingleton { INSTANCE // do something function }枚举单例模式写法简单,有字段也有方法,而且线程是安全的,在任何情况下都是一个单例。