单例模式

所谓单例模式就是一个类只有一个实例。

注意点:

1、多线程之间并发考虑,保证只有一个实例创建

2、保证序列化和反序列化后依然只有一个实例

 


 

常用实现方式

1、饥饿模式

public class Singleton {  
     private static Singleton instance = new Singleton();  
     private Singleton (){
     }
     public static Singleton getInstance() {  
     return instance;  
     }  
 }

关键点

  • 利用在类的加载过程中 ,static变量会初始化一次。先创建好一个实例
  • 提供静态方法获取此实例
  • 私有构造方法  

优点

  • 简单明了
  • 可读性好

缺点

  •  实例事先创建好,可能无效的占用内存空间,并未使用(一帮情况 既然用到了此类,很大可能也要要获取此实例的)
  • 反序列化会创建多个实例

 

2、懒汉模式(双重检查(DCL))

public class Singleton {  
      private volatile static Singleton singleton;  
      private Singleton (){
      }   
      public static Singleton getInstance() {  
      if (instance== null) {  
          synchronized (Singleton.class) {  
          if (instance== null) {  
              instance= new Singleton();  
          }  
         }  
     }  
     return singleton;  
     }  
 }

关键点

  • volatile关键字 防止CPU指令重排
  • 静态方法多线程并发考虑加锁 且 双重检查
  • 私有构造方法  

优点

  • 使用时才创建真正的实例 不浪费空间

缺点

  •  代码实现稍复杂
  • 不支持反序列化

  


 

3、懒汉模式(内部类实现)

public class Singleton { 
    private Singleton(){
    }
      public static Singleton getInstance(){  
        return SingletonHolder.sInstance;  
    }  
    private static class SingletonHolder {  
        private static final Singleton sInstance = new Singleton();  
    }  
}

  

关键点

  • 静态内部类的静态变量
  • 私有构造方法  

优点

  • 对比双重检查方式 代码跟简洁 高效

缺点

  • 不支持反序列化

 

4、枚举类型实现单例

public enum Singleton {  
     INSTANCE;  
     public void doSomeThing() {  
     }  
 }  

枚举本质就是一个类 extends Enum,本质还是一个类;且默认的构造方法是private的,JVM是禁止反射调用枚举的私有构造方法

基于枚举这些特点所以说 枚举是实现单例的最佳实践。

但可读性并不友好。

优点:即使反序列化依然只有一个实例!


 

总结:

1、不考虑序列化的情况 优先使用第1种 或 第3种

2、出于绝对的安全考虑 请使用 枚举方式 

posted @ 2019-08-17 22:39  蓝天随笔  阅读(356)  评论(0编辑  收藏  举报