单例模式(Singleton)

2017-10-15  本文已影响0人  NickelFox

一. 含义

二. 实现

  1. 普通单例模式
    • 实现方法:
    public class Singleton {
    
     private static Singleton sSingleton;//唯一实例
    
     /*私有构造方法,保证了外部无法创建类的实例*/
     private Singleton() {
    
     }
    
     /*通过该方法获取唯一实例*/
     public static Singleton getInstance() {
         if (sSingleton == null) {
             sSingleton = new Singleton();
         }
         return sSingleton;
     }
    }
    
    • 缺点:
      • 遇到多线程的时候就不能保证只有单一实例了

如何解决遇到多线程时不能保证只有一个实例呢?就引出了以下方法:

  1. 加了同步锁的单例模式
    • 实现:
    public class Singleton {
    
     private static Singleton sSingleton;//唯一实例
    
     /*私有构造方法,保证了外部无法创建类的实例*/
     private Singleton() {
    
     }
    
     /*通过该方法获取唯一实例,添加了synchronized关键字,确保一次只能有一个线程执行该方法*/
     public static synchronized Singleton getInstance() {
         if (sSingleton == null) {
             sSingleton = new Singleton();
         }
         return sSingleton;
     }
    }
    
    • 缺点:
      • 其实只有当第一次创建单例是才需要互斥,后面就不用了,但是互斥锁却一直存在,严重降低性能
  2. 即刻实例化,而不是延迟实例化
    • 实现:
    public class Singleton {
    
     private static Singleton sSingleton = new Singleton();//不管用不用的到,在程序一开始就执行静态初始化,直接初始化实例,就不会存在多个实例的问题了
    
     private Singleton() {
    
     }
    
     public static Singleton getInstance() {
         return sSingleton;
     }
    }
    
    • 缺点:
      • 要是不确定用不用的到,就会造成资源浪费
  3. 双重检查加锁的单例模式
    • 实现:
    public class Singleton {
    
     private volatile static Singleton sSingleton;//volatile确保了初始化后多线程能正确处理该实例
    
     private Singleton() {
    
     }
    
     public static Singleton getInstance() {
         if (sSingleton == null) {//检查实例,若不存在就进入同步区,这样就保证了只有第一次才进行同步
             synchronized (Singleton.class) {
                 if (sSingleton == null) {
                     sSingleton = new Singleton();
                 }
             }
         }
         return sSingleton;
     }
    }
    
    • 缺点:
      • JDK1.5之前JVM对volatile关键字的实现会导致双重检查加锁失效

三. 总结

上一篇下一篇

猜你喜欢

热点阅读