单例模式几种写法
1.饿汉式
public class SingletonInstance { //私有构造方法 private static SingletonInstance (){ } //声明成员变量 private static SingletonInstance singletonInstance = new SingletonInstance(); //对外提供接口获取该实例 public static SingletonInstance getSingletonInstance(){ return singletonInstance ; } }
2.懒汉式
public class SingletonInstance { //私有构造方法 private SingletonInstance (){ } //声明成员变量 private static SingletonInstance singletonInstance ; //对外提供接口获取该实例 public static SingletonInstance getSingletonInstance(){ if(singletonInstance == null){ singletonInstance = new SingletonInstance(); } return singletonInstance ; } }
饿汉式 懒汉式是经典的单例写法,但是线程不安全,当然,为保证线程安全,可以对getSingletonInstance()函数加锁,如下:
public static synchronized SingletonInstance getSingletonInstance(){ return singletonInstance = new SingletonInstance(); }
但是这样每次获取单例都会判断锁,会很消耗资源,所以饿汉式和懒汉式不推荐使用,推荐使用以下方式
3.double check lock(dcl)
public class SingletonInstance { //私有构造方法 private SingletonInstance (){ } //声明成员变量 private static SingletonInstance singletonInstance ; //对外提供接口获取该实例 public static SingletonInstance getSingletonInstance(){ if(singletonInstance == null){ synchronized (SingletonInstance.class){ //两次判断是否为null if(singletonInstance==null){ singletonInstance = new SingletonInstance(); } } } return singletonInstance ; } }
DCl 资源利用率高,执行效率也高,缺点是第一次加载的时候会比较慢,而且在高并发的时候,有可能会导致单例不成功(概率很小),推荐使用这种方式
4.静态内部类
public class SingletonInstance { //私有构造方法 private SingletonInstance (){ } private static class Builder{ //声明成员变量 private static SingletonInstance singletonInstance = new SingletonInstance(); } //对外提供接口获取该实例 public static SingletonInstance getSingletonInstance(){ return Builder.singletonInstance ; } }
这种方法,实例只会被创建一次,而且只有在被引用的时候创建,线程安全也能保证,所以推荐使用这种方式
5.以上四种方法,不管哪种方法,在反序列化的时候,都不能保证单例。但是使用枚举可以避免这个问题,枚举默认就是线程安全的
public enum Singleton { //enum枚举类 INSTANCE; }
但是枚举在android中是不建议使用的,因为枚举比constants消耗更大的内存,
6.单例管理类创建单例
public class SingletonManager { private static Map<String, Object> objMap = new HashMap<String,Object>();//使用HashMap作为缓存容器 private Singleton() { } public static void registerService(String key, Objectinstance) { if (!objMap.containsKey(key) ) { objMap.put(key, instance) ;//第一次是存入Map } } public static ObjectgetService(String key) { return objMap.get(key) ;//返回与key相对应的对象 } }
7.反序列化杜绝生成新的实例,需要加入以下这个函数
private Object readResolve() throws ObjectStreamException{ return INSTANCE; }