实际模式之-----单例模式(懒汉、饿汉、双重检验锁、静态内部类、枚举

 

  1. 解释:

    1. 单例类只能有一个实例
    2. 单例类必须自己创建自己的唯一实例
    3. 单例类必须给所有其他对象提供这一实例
  2. 是什么

    1. 保证一个类只有一个实例,并提供一个访问它的全局访问点。
  3. 为什么存在

    1. 解决全局使用的类频繁地创建与销毁。
  4. 怎么用

    1. 构造函数式私有的
  5. 优点

    1. 在内存里只有一个实例,减少了内存的开销,尤其是频繁的创建和销毁实例(比如管理学院首页页面缓存)。
    2. 避免对资源的多重占用(比如写文件操作)
  6. 缺点

    1. 没有接口,不能继承,与单一职责原则冲突,一个类应该只关心内部逻辑,而不关心外面怎么样来实例化
  7. 注意事项

    1. getInstance() 方法中需要使用同步锁 synchronized (Singleton.class) 防止多线程同时进入造成 instance 被多次实例化。
  8. 实现

    1. 图解实现

    2. 代码实现

      1. 饿汉模式基本实现

        1. 优点:没有加锁,执行效率会提高
        2. 缺点:类加载时就初始化,浪费内存
        3. 创建Singleton类
           

         public class Singleton {

                 private static Singleton instance = new Singleton();

                 private Singleton (){}

                 public static Singleton getInstance() {

                         return instance;

                 }

}    

 

                  2.懒汉模式实现

                         1.线程不安全实现

                                1. 是否Lazy初始化:是

                                 2.是否多线程安全:是

                                 3.优点:第一次调用才初始化,避免内存浪费

                                 4.缺点:必须加锁 synchronized 才能保证单例,但加锁会影响效率

                                 5.在多线程时不能正常工作

                                 6.实现

public class Singleton {

            private static Singleton instance;

            private Singleton (){}

            public static Singleton getInstance() {

            if (instance == null) {

                   instance = new Singleton();

             }

              return instance;

              }

}

                           2.线程安全实现 
                                  1.缺点:类加载时就初始化,浪费内存

                                  2.优点:没有加锁,执行效率会提高。

                                  3.这种方式具备很好的 lazy loading,能够在多线程中很好的工作,但是,效率很低,99% 情况下不需要同步。

public class Singleton {

          private static Singleton instance;

          private Singleton (){}

          public static synchronized Singleton getInstance() {

           if (instance == null) {

                instance = new Singleton();

            }

             return instance;

            }

}

                           注:当性能对程序不是很关键的时候使用。

                 3.双检锁/双重校验锁模式

                       1.Jdk版本:JDK5

                       2.是否lazy初始化:是

                       3.是否多线程安全:是

                       4.这种方式采用双锁机制,安全且在多线程情况下能保持高性能。

                       5.实现
 

public class Singleton {

           private volatile static Singleton singleton;

           private Singleton (){}

           public static Singleton getSingleton() {

           if (singleton == null) {

                  synchronized (Singleton.class) {

                        if (singleton == null) {

                              singleton = new Singleton();

                        }

                  }

           }

           return singleton;

          }

}

                  4.登记式/静态内部类

                        1.是否Lazy初始化:是

                        2.是否多线程安全:是

                        3.这种方式能达到双检锁方式一样的功效,但实现更简单。对静态域使用延迟初始化,应使用这种方式而不是双检锁方式。这种方式只适用于静态域的情况,双检锁方式可在实例域需要延迟初始化时使用。

实现

public class Singleton {

         private static class SingletonHolder {

                  private static final Singleton INSTANCE = new Singleton();

           }

          private Singleton (){}

          public static final Singleton getInstance() {

                   return SingletonHolder.INSTANCE;

           }

}

                  5.枚举

                        1.JDK5起

                        2.是否Lazy初始化:否

                        3.是否线程安全:是

                      4.这种实现方式还没有被广泛采用,但这是实现单例模式的最佳方法。它更简洁,自动支持序列化机制,绝对防止多次实例化

                        5.实现
 

public enum Singleton {

        INSTANCE;

        public void whateverMethod() { }

 }

注:一般情况下,不建议使用第2 种懒汉方式,建议使用第 1 种饿汉方式。只有在要明确实现 lazy loading 效果时,才会使用第 4 种登记方式。如果涉及到反序列化创建对象时,可以尝试使用第 5 种枚举方式。如果有其他特殊的需求,可以考虑使用第 3 种双检锁方式。、

版权声明:本博客为记录本人自学感悟,内容大多从网上学习与整理所得,若侵权请告知!

https://mp.csdn.net/postedit/80365677

猜你喜欢

转载自blog.csdn.net/qq_39657909/article/details/80397131