1、懒汉模式:
public class Singleton {
private static Singleton mSingleton;
private Singleton() {
}
/**
*
* 线程安全
*
* @return
*/
public static synchronized Singleton getInstance() {
if (mSingleton == null) {
mSingleton = new Singleton();
}
return mSingleton;
}
/**
* 线程不安全
*
* @return
*/
/*public static Singleton getInstance() {
if (mSingleton == null) {
mSingleton = new Singleton();
}
return mSingleton;
}*/
}
特点:
优点:单例只有在使用的时候才会被实例化,在一定程序上节约了资源
缺点:第一次加载时需要及时进行实例化,反应稍慢,最大的问题是每次调用getInstance都进行同步,行成不必要的同步开销。这种模式一般不建议使用。
2、饿汉模式:
public class Singleton {
private static final Singleton mSingleton = new Singleton();
private Singleton() {
}
public static Singleton getInstance() {
return mSingleton;
}
}
特点:
优点:没有加锁,执行效率会提高。
缺点:类加载时就初始化,浪费内存。
3、双重检查加载
public class Singleton {
private volatile static Singleton mSingleton = null;
private Singleton() {
}
public static Singleton getInstance() {
if (mSingleton == null) {
synchronized (Singleton.class) {
if (mSingleton == null) {
mSingleton = new Singleton();
}
}
}
return mSingleton;
}
}
特点:
优点:资源利用率高,第一次执行getInstance时单例对象才会被实例化,效率高
缺点:第一次加载时反应稍慢,而且volatile或多或少会影响到性能。
4、静态内部类
public class Singleton {
private Singleton() {
}
public static Singleton getInstance() {
return SingletonHolder.mSingleton;
}
private static class SingletonHolder {
private static final Singleton mSingleton = new Singleton();
}
}
特点:
当第一次加载Singleton类时并不会初始化mSingleton,只能第一次调用getInstance方法时才会导致mSingleton被初始化。因此,第一次调用getInstance方法会导致虚拟机加载SingletonHolder类,这种方式不仅能确保安全,也能保证单例对象的唯一性,同时也延迟了单例的实例化。推荐性使用该实现方式;
5、枚举
public enum SingletonEnum {
SINGLETON;
}
特点:
写法简单,线程安全,能杜绝单例对象在被反序列化的重新生成新的对象
注意:除了枚举,上面几种单例模式如果想杜绝单例对象在被反序列化的重新生成新的对象,要实现Serializable接口
private Object readResolve() throws ObjectStreamException {
return SingletonHolder.mSingleton;
}
6、使用容器实现单例模式
public class SingletonManager {
private static Map<String, Object> mSingletonManager = new HashMap<String, Object>();
private SingletonManager() {
}
public static void addSingletonToMangager(String key, Object singleton) {
if (!mSingletonManager.containsKey(key)) {
mSingletonManager.put(key, singleton);
}
}
public static Object getSingletonFromManager(String key) {
return mSingletonManager.get(key);
}
}
特点:
在程序的初始,将多种单例类型注入到一个统一的管理类中,在使用时根据key获取对象对应类型的对象,这使我们可以管理多种类型的单例,并且使用时可以通过统一的接口进行获取。
总结
1、构造函数不对外开放,private;
2、通过一个静态方法或者枚举返回单例类对象;
3、确保单例类的对象有且只有一个,尤其是在多线程环境下;
4、确保单例类对象在反序列化时不会重新构建对象。