单例模式

2018-11-28  本文已影响0人  幸运星32
1:饿汉模式
public class Singleton{
    private static Singleton instance = new Singleton();
    private Singleton(){
    }
    public static Singleton getInstance(){
          return instance;
    }
}

这种方式在类加载时就完成了初始化,所以类加载会慢一些,但是获取对象的速度块,它是基于类加载机制,避免类多线程的同步问题,但是没有达到懒加载的效果,如果一直没有使用该类,会造成内存浪费。之所以叫做饿汉,是因为它获取对象的速度像饿汉吃饭的速度一样快。

2:懒汉模式(线程不安全)
public class Singleton{
      private static Singleton instance;
      private Singleton(){
      }
      public static Singleton getInstance(){
         if(instance == null){
            instance = new Singleton();
      }
      return instance;
      }
}

懒汉模式声明了一个静态对象,在用户第一次调用的时候初始化,节约了资源,但是第一次加载时需要实例化,反应较慢,而且在多线程时不能正常工作,他是线程不安全的模式。之所以叫他懒汉是因为他只有在使用的时候才初始化。

3:懒汉模式(线程安全的)
public class Singleton{
    private static Singleton instance;
    private Singleton(){
    }
    public static synchronized Singleton getInstance(){
        if(instance == null){
            instance = new Singleton();
        }
    return instance;
    }
}

这种写法能够在多线程中很好的工作,但是每次调用getInstance方法时都要进行同步,会造成不必要的同步开销,而且大部分时候我们用不到同步,所以不建议用此模式。

4:双重检查模式(DCL)
public class Singleton{
  private volatile static Singleton instance;
  private Singleton(){
  }
  public static Singleton getInstance(){
      if(instance == null){
          synchronized(Singleton.class){
              if(instance == null){
                  instance = new Singleton();
              }
          }
      }
  }
}

这种写法其实是对线程安全的懒汉模式的一种优化,在getinstance方法中对instance进行了两次空判断,第一次是为了不必要的同步,第二次是在instance为空的情况下才创建实例。这里的volatile关键字,是为了满足变量变化时,实时的体现在共享内存中,放在这里可能会影响一些性能,但考虑到程序的正确性,牺牲这点性能是值得的。DCL的优点是资源利用率搞,第一次执行getinstance的时候才实例化对象,效率高。但是在高并发的情况下会出现失效的问题。

5:静态内部类单例模式
public class Singleton{
  private Singleton(){

  }
  public static Singleton getInstance(){
    return SingletonHolder.sInstance;
  }

  private static class SingletonHolder{
    private static final Singleton sInstance = new Singleton();
  }
}

这种形式在第一次加载Singleton类的时候并不会初始化sInstance,只有在第一次调用getInstance方法时虚拟机加载SingleHolder并初始化sInstance。这样不仅能确保线程安全,也能保证Singleton类的唯一性。所以静态内部类单例模式是比较推荐的模式。

6:枚举单例
public enum Singleton{
  INSTANCE;
  public void doSomeThing(){

  }
}

枚举单例是线程安全的,并且在任何情况下都是单例。但是在Android开发中枚举是不推荐使用的。

上一篇下一篇

猜你喜欢

热点阅读