2.设计模式--创建者模式--单例设计模式

2.设计模式–创建者模式–单例设计模式

一个程序整个运行过程中,该实例的对象只被创建一次。

2.1单例设计模式的分类:

饿汉式:类加载时创建单例类的对象
懒汉式:类加载时不创建单例类的对象,第一次访问时创建单例类的对象。

2.2单例设计模式

2.2.1饿汉式(静态变量)

/**
 * 饿汉式:静态变量创建类的对象
 */
public class Singleton {

    //构造方法私有
    private Singleton(){}

    //静态变量创建类的对象
    private static Singleton instance = new Singleton();

    //对外提供静态方法
    public static Singleton getInstance(){
        return instance;
    }
}

如果对象不创建会导致内存浪费。

2.2.2 饿汉式(静态代码块)

/**
 * 饿汉:静态代码块
 */
public class Singleton2 {

    //构造方法私有
    private Singleton2(){}

    private static Singleton2 instance;
    //静态代码块
    static{
        instance = new Singleton2();
    }

    //对外提供静态对象获取该对象
    public static Singleton2 getInstance(){
        return instance;
    }
}

如果对象不创建会导致内存浪费。

2.2.3 懒汉式(方式一)

/**
 * 懒汉式
 */
public class Singleton3 {

    /**
     * 构造方法私有
     */
    private Singleton3(){};

    //在成员位置创建该类的对象
    private static Singleton3 instance;

    /**
     * 静态获取方法
      * @return
     */
    public static Singleton3 getInstance(){
       if(instance==null){
           instance = new Singleton3();
       }
        return instance;
    }
}

多线程环境,会出现线程安全问题。

2.2.4 懒汉式(方法上synchronized锁)

public class Singleton4 {

    //私有构造方法
    private Singleton4(){};

    //在成员位置创建该类的对象
    private static Singleton4 instance;

    /**
     * 提供静态方法获取变量
     */
    public synchronized static Singleton4 getinstance(){
      if(instance==null){
          instance = new Singleton4();
      }
        return instance;
    }
}

在初始化instance的时候才会出现线程安全问题,一旦初始化完成就不存在了。

2.2.4 懒汉式(双重检查锁)

public class Singleton5 {

    private Singleton5(){};

    private static Singleton5 instance;

    public static Singleton5 getInstance(){
       if(instance==null){
           //第一次判断,如果instance不为null,不进入抢锁阶段,直接返回实例
           synchronized (Singleton5.class){
               //抢到锁之后再次判断是否为null
               if(instance==null){
                   instance = new Singleton5();
               }
           }
       }
        return null;
    }
}

在多线程的情况下,可能会出现空指针问题,出现问题的原因是JVM在实例化对象的时候会进行优化和指令重排序操作

2.2.5懒汉式(volatile关键字)

public class Singleton6 {

    private Singleton6(){};
    //volatile参数存在,不会指令重排序
    private static volatile Singleton6 instance;

    public static Singleton6 getInstance(){
        if(instance==null){
            //第一次判断,如果instance不为null,不进入抢锁阶段,直接返回实例
            synchronized (Singleton6.class){
                //抢到锁之后再次判断是否为null
                if(instance==null){
                    instance = new Singleton6();
                }
            }
        }
        return null;
    }
}

2.2.6懒汉式(静态内部类方式)

public class Singleton7 {

    //私有方法构造
    private Singleton7(){};

    private static class singletonHolder{
        private static final Singleton7 INSTANCE = new Singleton7();
    }

    public static Singleton7 getInstance(){
        return singletonHolder.INSTANCE;
    }
}

静态属性由于被 static修饰,保证只被实例化一次,并且严格保证实例化顺序

3.1破坏单例模式

1.序列化和反序列化

public class SingletonDemo {

    public static void main(String[] args) throws Exception {
        //往文件中写对象
        writeObject2File();
        //从文件中读取对象
        Singleton s1 = readObjectFromFile();
        Singleton s2 = readObjectFromFile();

        //判断两个反序列化后的对象是否是同一个对象
        System.out.println(s1 == s2);
    }

    private static Singleton readObjectFromFile() throws Exception {
        //创建对象输入流对象
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("D:\\a.txt"));
        //第一个读取Singleton对象
        Singleton instance = (Singleton) ois.readObject();

        return instance;
    }

    public static void writeObject2File() throws Exception {
        //获取Singleton类的对象
        Singleton instance = Singleton.getInstance();
        //创建对象输出流
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("D:\\a.txt"));
        //将instance对象写出到文件中
        oos.writeObject(instance);
    }
}

2.反射

public class Test {
    public static void main(String[] args) throws Exception {
        //获取Singleton类的字节码对象
        Class clazz = Singleton.class;
        //获取Singleton类的私有无参构造方法对象
        Constructor constructor = clazz.getDeclaredConstructor();
        //取消访问检查
        constructor.setAccessible(true);

        //创建Singleton类的对象s1
        Singleton s1 = (Singleton) constructor.newInstance();
        //创建Singleton类的对象s2
        Singleton s2 = (Singleton) constructor.newInstance();

        //判断通过反射创建的两个Singleton对象是否是同一个对象
        System.out.println(s1 == s2);
    }
}

相关推荐

  1. 2.设计模式--创建者模式--设计模式

    2024-07-18 20:08:03       21 阅读
  2. 笨蛋学设计模式创建者模式-模式2

    2024-07-18 20:08:03       47 阅读
  3. 设计模式2

    2024-07-18 20:08:03       25 阅读
  4. 设计模式(2):模式

    2024-07-18 20:08:03       34 阅读
  5. 设计模式 创建型】模式

    2024-07-18 20:08:03       57 阅读
  6. 设计模式-模式创建型)

    2024-07-18 20:08:03       28 阅读
  7. 设计模式】:模式

    2024-07-18 20:08:03       53 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-18 20:08:03       70 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-18 20:08:03       74 阅读
  3. 在Django里面运行非项目文件

    2024-07-18 20:08:03       62 阅读
  4. Python语言-面向对象

    2024-07-18 20:08:03       72 阅读

热门阅读

  1. 编程中的智慧之设计模式二

    2024-07-18 20:08:03       23 阅读
  2. 轻松掌握PyTorch CUDA编程,机器学习如虎添翼

    2024-07-18 20:08:03       23 阅读
  3. 【无标题】Elasticsearch for windows

    2024-07-18 20:08:03       24 阅读
  4. 数据仓库实践:了解和定义指标

    2024-07-18 20:08:03       23 阅读
  5. 互联网摸鱼日报(2024-07-18)

    2024-07-18 20:08:03       23 阅读
  6. 【Unity】RPG2D龙城纷争(十三)升级系统

    2024-07-18 20:08:03       27 阅读
  7. 使用 GO 和 Python 分别写爬虫的区别

    2024-07-18 20:08:03       22 阅读
  8. 数据库系统概论:数据库查询语言 SQL

    2024-07-18 20:08:03       22 阅读
  9. 017.自定义指纹浏览器-传参固定指纹(二)

    2024-07-18 20:08:03       18 阅读
  10. 【时时三省】单元测试 简介

    2024-07-18 20:08:03       23 阅读