zoukankan      html  css  js  c++  java
  • 单例设计模式详解

    单例模式

    1、饿汉式(延迟加载)

    指不管用不用这个类,此类都会被创建。

    代码:

    public class EagerSingleton {
      private static EagerSingleton eagerSingleton=new EagerSingleton();
      public static EagerSingleton getInstance(){
          return eagerSingleton;
      }
    }

    2、懒汉式(非延迟加载)

    指用到这个类的时候,才会被创建。

    代码:(此类线程不安全)

    public class LazySingleton {
      private static LazySingleton lazySingleton=null;
      private static LazySingleton getInstance(){
          if(lazySingleton==null){
              lazySingleton=new LazySingleton();
          }
          return lazySingleton;
      }
    }

    3、线程安全的三种单例写法

    3.1、双重检查单例写法

    代码:

    1 public class DoubleCheckSingleton {
    2    private static DoubleCheckSingleton doubleCheckSingleton=null;
    3    public static DoubleCheckSingleton getInstance(){
    4        if(doubleCheckSingleton==null){
    5            synchronized (DoubleCheckSingleton.class){
    6                if(doubleCheckSingleton==null){
    7                    doubleCheckSingleton=new DoubleCheckSingleton();
    8               }
    9           }
    10       }
    11        return doubleCheckSingleton;
    12   }
         private int a;
         public int getA(){
             return a;
        }
    13}

    双重检查的写法会引发有序性问题。

    分析:

    对象在JVM中的创建步骤大致分为以下三步:

    1.new:开辟JVM堆中的内存空间

    2.将内存空间初始化(指的就是对象的成员变量初始化为0值)

    3.将内存空间地址(引用地址)赋值给引用类型的变量

    在new对象的时候,JIT即时编译器会根据运行情况,对对象创建的过程进行指令重排序(按照1、3、2步骤执行)。

    如果线程1执行到了第7行,只完成了1、3步加载,第2步还没有执行的时候,这时线程2从第4行开始执行,这时doubleCheckSingleton不为空,直接返回doubleCheckSingleton。当调用DoubleCheckSingleton的getA()方法时,就会报错,因为这时成员变量a还没有被初始化。

    为了解决这个问题,可以给doubleCheckSingleton变量加上volatile关键字,防止重排序。

    private volatile static DoubleCheckSingleton doubleCheckSingleton=null;

     

    3.2、内部静态类单例写法

    代码:

    public class InnerStaticSingleton {
      private static class SingletonFactory{
          private static InnerStaticSingleton instance=new InnerStaticSingleton();
      }
       
      public InnerStaticSingleton getInstance(){
          return SingletonFactory.instance;
      }
    }

    原理:

    内部静态类只有在被调用时,才会执行内部静态类中的静态代码块、给成员静态变量赋值,并且只执行一次。所以既保证了单例,又保证了延迟加载。

     

    3.3、枚举单例写法

    代码:

    public enum  EnumSingleton {
      INSTANCE;
      public void talk() {
          System.out.println("This is an EnumSingleton " + this.hashCode());
      }
    }

     

    4、破坏单例

    4.1、反射破坏单例

    代码:

    public class ReflectBreakSingleton {
      public static void main(String[] args) throws Exception {
          Class clazz = InnerStaticSingleton.class;
          InnerStaticSingleton singleton1 = (InnerStaticSingleton) clazz.newInstance();
          InnerStaticSingleton singleton2 = (InnerStaticSingleton) clazz.newInstance();
          System.out.println(singleton1 == singleton2);//false
      }
    }

     

    4.2、反序列化破坏单例

    如果单例实现了序列化,则可执行下列代码破坏单例:

    public class SerializeBreakSingleton {
      public static void main(String[] args)throws Exception{
          InnerStaticSingleton innerStaticSingleton=InnerStaticSingleton.getInstance();
          ByteArrayOutputStream byteArrayOutputStream=new ByteArrayOutputStream();
          ObjectOutputStream outputStream=new ObjectOutputStream(byteArrayOutputStream);
          outputStream.writeObject(innerStaticSingleton);

          ByteArrayInputStream byteArrayInputStream=new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
          ObjectInputStream objectInputStream=new ObjectInputStream(byteArrayInputStream);
          InnerStaticSingleton innerStaticSingleton1=(InnerStaticSingleton) objectInputStream.readObject();

          System.out.println(innerStaticSingleton==innerStaticSingleton1);
      }
    }

     

  • 相关阅读:
    macbook466加了两条1333金士顿正常
    spring 使用 groovy 的 utf8 问题
    jQuery Pagination Plugin Demo
    ssh 二级跳 转
    实战 Groovy: 用 curry 过的闭包进行函数式编程
    无刷新分页 jquery.pagination.js 张龙豪 博客园
    用fgets()函数从屏幕上输入一字符串_BenRuanChinaUnix博客
    What Is My IP Shows Your IP Address
    Chapter 24. Dynamic language support
    什么是SQA?
  • 原文地址:https://www.cnblogs.com/BonnieWss/p/12201059.html
Copyright © 2011-2022 走看看