美文网首页
单列模式的四种写法

单列模式的四种写法

作者: 笑才 | 来源:发表于2018-10-26 23:11 被阅读0次

    1、懒汉模式(线程不安全的)

    public class SingletonTest01 {
    
        public static void main(String[] args) {
            new Thread(){
                public void run(){
                    System.out.println(MySingleton01.getInstance());
                }
            }.start();
            new Thread(new Runnable(){
                public void run() {
                    System.out.println(MySingleton01.getInstance());
                }
            }).start();
        }
    }
    //懒汉模式(是线程不安全的),如果多线程处理时,需加synchronized进行处理
    class MySingleton01{
        //创建一个私有的静态的类(不实例化)
        private static MySingleton01 mySingleton01=null;//懒得实例化,所以是懒汉
        //创建私有的构造方法
        private MySingleton01(){}
        //创建一个开放的实例化方法,供外界获取对象
        public static MySingleton01 getInstance(){
            if(mySingleton01==null){
                try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}
                mySingleton01 = new MySingleton01();
                return mySingleton01;
            }else{
                return mySingleton01;
            }
        }
    }
    
    此处mySingleton01用volatile修饰会更好
    改为线程安全的:
    class MySingleton01{
        //创建一个私有的静态的类(不实例化)
        private volatile static MySingleton01 mySingleton01=null;//懒得实例化,所以是懒汉
        //创建私有的构造方法
        private MySingleton01(){}
        //创建一个开放的实例化方法,供外界获取对象
        public static MySingleton01 getInstance(){
            if(mySingleton01==null){//Java 中的双重检查技术(Double-Check)
                synchronized (MySingleton01.class) {
                    try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}
                    if(mySingleton01==null){
                        mySingleton01 = new MySingleton01();
                    }
                }       
                return mySingleton01;
            }else{
                return mySingleton01;
            }
        }
    }
    

    2、饿汉模式(线程安全的)

    public class SingletonTest02 {
        public static void main(String[] args) {
            new Thread(){
                public void run(){
                    System.out.println(MySingleton02.getInstance());
                }
            }.start();
            new Thread(new Runnable(){
                public void run() {
                    System.out.println(MySingleton02.getInstance());
                }
            }).start();
        }
    }
    //饿汉模式(是线程安全的)
    class MySingleton02{
        //创建一个私有的静态的类(实例化)
        private static MySingleton02 mySingleton=new MySingleton02();
        //创建私有的构造方法
        private MySingleton02(){}
        //创建一个开放的实例化方法,供外界获取对象
        public  static MySingleton02 getInstance(){
            return mySingleton;
        }
    }
    

    3、延迟加载的饿汉模式(线程安全,而且节省资源,类加载时不会实例化对象,推荐使用)

    public class SingletonTest03 {
    
        public static void main(String[] args) {
            new Thread(){
                public void run(){
                    System.out.println(MySingleton03.getInstance());
                }
            }.start();
            new Thread(new Runnable(){
                public void run() {
                    System.out.println(MySingleton03.getInstance());
                }
            }).start();
        }
    }
    //延迟加载的饿汉模式(线程安全,而且节省资源,类加载时不会实例化对象,只有在调用getInstance方法后,才会实例化对象)
    class MySingleton03{
        //创建一个私有的静态的内部类,持有对象(实例化)
        private static class MySingleton03Holder{
            private static MySingleton03 mySingleton=new MySingleton03();
        }
        //创建私有的构造方法
        private MySingleton03(){}
        //创建一个开放的实例化方法,供外界获取对象
        public  static MySingleton03 getInstance(){
            return MySingleton03Holder.mySingleton;
        }
    }
    

    4、枚举类型实现单例(除了不能延迟加载,其它特性都是极好的,是最安全的,是所有写法中唯一一种不能通过反射或反序列化破解单例的写法,推荐使用)

    public class SingletonTest04 {
        public static void main(String[] args) {
            System.out.println(MySingleton04.INSTANCE==MySingleton04.INSTANCE);
            MySingleton04 m1 = MySingleton04.INSTANCE;
            MySingleton04 m2 = MySingleton04.INSTANCE;
            m1.say();
            m1.say();
            System.out.println(m2.getI());
        }
    }
    
    enum MySingleton04{//枚举类型
        INSTANCE;
        private int i=0;
        public void say(){
            System.out.println("Hello World !!!");
            i++;
        }
        public int getI() {
            return i;
        }
    }
    

    5、通过反射的方式破解单例模式

    public class SingletonTest05 {
        public static void main(String[] args) throws ClassNotFoundException, SecurityException, NoSuchMethodException, IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException {
            System.out.println(MySingleton05.getInstance());
            System.out.println(MySingleton05.getInstance());
            //通过反射的方式直接调用私有构造器
            Class<MySingleton05> clazz =(Class<MySingleton05>) Class.forName("com.primeton.singleton.MySingleton05");
            Constructor<MySingleton05> c =clazz.getDeclaredConstructor(null);
            c.setAccessible(true);
            MySingleton05 mySingleton1 = c.newInstance(null);
            MySingleton05 mySingleton2 = c.newInstance(null);
            System.out.println(mySingleton1);
            System.out.println(mySingleton2);
        }
    }
    class MySingleton05{
        //创建一个私有的静态的类(实例化)
        private static class MySingleton03Holder{
            private static MySingleton05 mySingleton=new MySingleton05();
        }
        //创建私有的构造方法
        private MySingleton05(){}
        //创建一个开放的实例化方法,供外界获取对象
        public  static MySingleton05 getInstance(){
            return MySingleton03Holder.mySingleton;
        }
        public static void say(){
            System.out.println("Hello World !!!");
        }
    }
    
    结果:
    com.primeton.singleton.MySingleton05@1cc2ea3f
    com.primeton.singleton.MySingleton05@1cc2ea3f
    com.primeton.singleton.MySingleton05@40a0dcd9
    com.primeton.singleton.MySingleton05@1034bb5
    结论:通过该方式让该单例类产生了多个对象
    

    6、通过序列化与反序列化的方式破解单例模式(被破解的单例需实现了Serializable接口才行)

    public class SingletonTest06 {
        public static void main(String[] args) throws Exception {
            System.out.println(MySingleton05.getInstance());
            System.out.println(MySingleton05.getInstance());
            //通过序列化与反序列化的方式破解单例模式
            ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(new File("D://ceshi.txt")));
            oos.writeObject(MySingleton06.getInstance());
            oos.flush();
            oos.close();
            ObjectInputStream ois = new ObjectInputStream(new FileInputStream(new File("D://ceshi.txt")));
            MySingleton06 mySingleton1 = (MySingleton06) ois.readObject();
            System.out.println(mySingleton1);
        }
    }
    class MySingleton06 implements Serializable{
        //创建一个私有的静态的类(实例化)
        private static class MySingleton03Holder{
            private static MySingleton06 mySingleton=new MySingleton06();
        }
        //创建私有的构造方法
        private MySingleton06(){}
        //创建一个开放的实例化方法,供外界获取对象
        public  static MySingleton06 getInstance(){
            return MySingleton03Holder.mySingleton;
        }
        public static void say(){
            System.out.println("Hello World !!!");
        }
    }
    结果:
    com.primeton.singleton.MySingleton05@3fbefab0
    com.primeton.singleton.MySingleton05@3fbefab0
    com.primeton.singleton.MySingleton06@4d546e25
    结论:通过该方式让该单例类产生了多个对象
    

    相关文章

      网友评论

          本文标题:单列模式的四种写法

          本文链接:https://www.haomeiwen.com/subject/baxrtqtx.html