• 单例模式


    强烈推荐的方式:使用枚举:

    一个错误的单例模式

    /*
    *   一个有问题的单例模式
    * */
    public class Single1 {
        private Single1(){}
        private Single1 s = null;
    
        public Single1 getSingle1(){
            //这样子写有问题
            if (s == null){
                //如果两个程序同时走到这里,就会返回两个实例
                return new Single1();
            }else{
                return s;
            }
        }
    }

    几个普通状态线程安全的单例模式,但是可以被反射破解,也可以被序列化和反序列化破解

    /*
    *   一个饿汉,安全的单例模式,推荐
    * */
    public class Single2 implements Serializable {
        private static Single2 s = new Single2();
        private Single2(){}
        public static Single2 getSingle2(){
            return s;
        }
    }
    package com.zhuopeng.desigh_model.single_model;
    
    import java.io.Serializable;
    
    /*
     *   一个懒汉,双重检查模式,推荐
     *   这个例子,对第一个错误的事例进行了改进。如果不使用双重检查模式,每次调用getInstance()都直接进入同步代码块的话,性能不好
     *   注意:
     *       instance 使用了volatile修饰
     *   原因:代码的重排序,在进行 new Single3()的 时候,需要执行以下的三个步骤
     *   memory=allocate(); //1:分配内存空间
     *   ctorInstance();   //2:初始化对象
     *   singleton=memory; //3:设置singleton指向刚排序的内存空间
     *   如果 2 和 3进行 了重排序, 1-3-2的顺序,如果线程A执行了3,这个时候线程B判断if(instance == null)结果为False,直接返回instance,
     *   就会返回一个没后初始化的instance
     * */
    public class Single3 implements Serializable {
        private Single3() {
        }
    
        private static volatile Single3 instance;
    
        public static Single3 getInstance() {
            if (instance == null) {
                synchronized (Single3.class) {
                    if (instance == null) {
                        instance = new Single3();
                    }
                }
            }
            return instance;
        }
    }
    package com.zhuopeng.desigh_model.single_model;
    
    import java.io.Serializable;
    
    /*
    *   懒汉模式,在调用getInstance() 的时候才初始化一个实例,推荐
    *   外部的静态变量,静态代码块在加载类的时候就运行了
    *   但是内部的静态类,在外部调用的时候才开始执行静态变量,静态代码块
    * */
    public class Single4 implements Serializable {
        private Single4(){}
        public static Single4 getInstance(){
            return Inner.s;
        }
        private static class Inner{
            private static final Single4 s = new Single4();
        }
    
    }

    升级过后的单例模式,序列化反序列化之后也只有一个实例,也不可以通过反射破解

    package com.zhuopeng.desigh_model.single_model;
    
    import java.io.Serializable;
    
    public class Single6 implements Serializable {
        //设置一个静态的flag,当类加载的时候这个flag就被创建了
        private static boolean flag = false;
        private static Single6 single6 = new Single6();
        private Single6(){
            //当上面那个静态变量new的时候flag就会改变,以后通过反射再次创建的时候,就不能创建了
            if (!flag){
                flag = true;
            }else{
                throw new RuntimeException("单例被破坏");
            }
        }
        public static Single6 getInstance(){
            return single6;
        }
        //用于序列化与反序列化的时候,可能会创建出不同的单例
        private Object readResolve(){
            return single6;
        }
    
    }

    一个强烈推荐的:使用枚举的单例模式:

    package com.zhuopeng.desigh_model.single_model;
    
    
    import java.io.Serializable;
    
    public enum  Single5 implements Serializable {
        INSTANCE;
        int id;
        String name;
    
        public void setId(int id) {
            this.id = id;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getId() {
            return id;
        }
    
        public String getName() {
            return name;
        }
    }

    测试:

    package com.zhuopeng.desigh_model.single_model;
    
    import java.lang.reflect.Constructor;
    import java.lang.reflect.InvocationTargetException;
    
    /*
    *   除了枚举构造的单例模式,其他方法构造的单例模式都可以通过反射来进行破解
    *
    * */
    public class Test1 {
        public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
            //破解使用静态变量构造的单例模式
            Constructor cos = Single2.class.getDeclaredConstructor();
            //取消访问检查功能
            cos.setAccessible(true);
            Single2 s1 = (Single2) cos.newInstance();
            Single2 s2 = (Single2) cos.newInstance();
    
            //生成了四个实例
            System.out.println(s1);
            System.out.println(s1.getSingle2());
            System.out.println(s2);
            System.out.println(s2.getSingle2());
    
            //下面是升级版本的,防止破坏的单例模式
            Constructor constructor = Single6.class.getDeclaredConstructor();
            constructor.setAccessible(true);
            //抛出异常,因为Single6的内部静态类已经new出一个实例了
            Single6 s6 = (Single6)constructor.newInstance();
            System.out.println("s6"+ s6);
    
    
    
        }
    }
    package com.zhuopeng.desigh_model.single_model;
    
    import java.io.*;
    
    /*
    *   部分单例模式在序列化和反序列化后会产生多个实例,除非单例类中重写了readResolve() 方法
    * */
    public class Test2 {
        public static void main(String[] args) throws IOException, ClassNotFoundException {
            Single6 single6 = Single6.getInstance();
    
            FileOutputStream fileOutputStream = new FileOutputStream("o");
            ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
            objectOutputStream.writeObject(single6);
            objectOutputStream.close();
            fileOutputStream.close();
    
            FileInputStream fileInputStream = new FileInputStream("o");
            ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
            Single6 s1 = (Single6)objectInputStream.readObject();
            objectInputStream.close();
            fileInputStream.close();
    
            //结果显示是一个实例,因为Single6中重写了 readResolve()方法,如果没有重写的话,就是两个不同的实例了
            System.out.println(single6);
            System.out.println(s1);
    
    
        }
    }
     
  • 相关阅读:
    20172311《程序设计与数据结构》第六周学习总结
    20172311 2018-2019-1 《程序设计与数据结构》课堂测试修改报告
    20172323 2018-2019-1《程序设计与数据结构》课程总结
    20172323 2018-2019-1 《程序设计与数据结构》课堂测试报告
    20172323 2018-2019-1 《程序设计与数据结构》实验三报告
    20172323 2018-2019-1 《程序设计与数据结构》第九周学习总结
    20172323 2018-2019-1 《程序设计与数据结构》实验二报告
    20172323 2018-2019-1 《程序设计与数据结构》第八周学习总结
    20172323 2018-2019-1 《程序设计与数据结构》第七周学习总结
    20172323 2018-2019-1 《程序设计与数据结构》第六周学习总结
  • 原文地址:https://www.cnblogs.com/da-peng/p/12024508.html
Copyright © 2020-2023  润新知