单例模式几种写法

时间:2022-06-15 05:34:38

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;
}