zoukankan      html  css  js  c++  java
  • 单例模式

    饿汉式(静态常量):

    /**
     * 饿汉式(静态常量)
     *
     * 1.构造器私有
     * 2.定义一个静态常量保存一个唯一的实例对象(单例)
     * 3.提供一个静态方法返回单例对象
     */
    public class Singleton01 {
    
        public static final Singleton01 INSTANCE = new Singleton01();
    
        private Singleton01() {}
    
        public static Singleton01 getInstance() {
            return INSTANCE;
        }
    
    }
    
    class Test01 {
        public static void main(String[] args) {
            Singleton01 s1 = Singleton01.getInstance();
            Singleton01 s2 = Singleton01.getInstance();
            System.out.println(s1 == s2); // true
        }
    }

    饿汉式(静态代码块):

    /**
     * 饿汉式(静态代码块)
     *
     * 1.构造器私有
     * 2.定义一个静态常量保存一个唯一的实例对象(单例),通过静态代码块初始化单例对象
     * 3.提供一个静态方法返回单例对象
     */
    public class Singleton02 {
    
        public static final Singleton02 INSTANCE;
    
        static {
            INSTANCE = new Singleton02();
        }
    
        private Singleton02() {}
    
        public static Singleton02 getInstance() {
            return INSTANCE;
        }
    
    }
    
    class Test02 {
        public static void main(String[] args) {
            Singleton02 s1 = Singleton02.getInstance();
            Singleton02 s2 = Singleton02.getInstance();
            System.out.println(s1 == s2); // true
        }
    }

    懒汉式(线程不安全,不推荐这样写):

    /**
     * 懒汉式(线程不安全,不推荐这样写)
     *
     * 1.构造器私有
     * 2.定义一个静态变量存储一个单例对象(定义时不初始化该对象)
     * 3.提供一个静态方法返回单例对象,返回前先询问是否有,有则直接返回,没有则创建新的返回
     */
    public class Singleton03 {
    
        public static Singleton03 instance;
    
        private Singleton03() {}
    
        public static Singleton03 getInstance() {
            if (instance == null) {
                instance = new Singleton03();
            }
            return instance;
        }
    
    }
    
    class Test03 {
        public static void main(String[] args) {
            Singleton03 s1 = Singleton03.getInstance();
            Singleton03 s2 = Singleton03.getInstance();
            System.out.println(s1 == s2); // true / false
        }
    }

    懒汉式(线程安全,性能差,不推荐这样写):

    /**
     * 懒汉式(线程安全,性能差,不推荐这样写)
     *
     * 1.构造器私有
     * 2.定义一个静态变量存储一个单例对象(定义时不初始化该对象)
     * 3.提供一个静态同步方法返回单例对象,返回前先询问是否有,有则直接返回,没有则创建新的返回
     */
    public class Singleton04 {
    
        public static Singleton04 instance;
    
        private Singleton04() {}
    
        public static synchronized Singleton04 getInstance() {
            if (instance == null) {
                instance = new Singleton04();
            }
            return instance;
        }
    
    }
    
    class Test04 {
        public static void main(String[] args) {
            Singleton04 s1 = Singleton04.getInstance();
            Singleton04 s2 = Singleton04.getInstance();
            System.out.println(s1 == s2); // true
        }
    }

    懒汉式(线程不安全,不推荐这样写):

    /**
     * 懒汉式(线程不安全,不推荐这样写)
     *
     * 1.构造器私有
     * 2.定义一个静态变量存储一个单例对象(定义时不初始化该对象)
     * 3.提供一个静态方法返回单例对象,返回前先询问是否有,有则直接返回,没有则创建新的返回
     */
    public class Singleton05 {
    
        public static Singleton05 instance;
    
        private Singleton05() {}
    
        public static Singleton05 getInstance() {
            if (instance == null) {
                // 性能得到了优化,但是依然不能保证第一次获取对象的线程安全
                synchronized (Singleton05.class) {
                    instance = new Singleton05();
                }
            }
            return instance;
        }
    
    }
    
    class Test05 {
        public static void main(String[] args) {
            Singleton05 s1 = Singleton05.getInstance();
            Singleton05 s2 = Singleton05.getInstance();
            System.out.println(s1 == s2); // true / false
        }
    }

    懒汉式(线程安全):其实私有化构造器并不保险,存在反射攻击;还可能出现反序列化攻击的风险

    /**
     * 懒汉式(线程安全)
     *
     * 1.构造器私有
     * 2.定义一个静态变量(用volatile修饰,保证可见性和禁止指令重排序)存储一个单例对象(定义时不初始化该对象)
     * 3.提供一个静态方法返回单例对象,返回前先询问是否有,有则直接返回,没有则创建新的返回
     */
    public class Singleton06 {
    
        public static volatile Singleton06 instance;
    
        private Singleton06() {}
    
        public static Singleton06 getInstance() {
            if (instance == null) {
                synchronized (Singleton06.class) {
                    if (instance == null) {
                        instance = new Singleton06();
                    }
                }
            }
            return instance;
        }
    
    }
    
    class Test06 {
        public static void main(String[] args) {
            Singleton06 s1 = Singleton06.getInstance();
            Singleton06 s2 = Singleton06.getInstance();
            System.out.println(s1 == s2); // true
        }
    }

    懒汉式(基于类的初始化实现延迟加载和线程安全的单例设计):存在反射攻击和反序列化攻击的风险

    /**
     * 懒汉式(基于类的初始化实现延迟加载和线程安全的单例设计)
     *
     * 1.构造器私有
     * 2.提供一个静态内部类,里面提供一个常量存储一个单例对象
     * 3.提供一个静态方法返回静态内部类中的单例对象
     */
    public class Singleton07 {
    
        /*private static int i = 0;
        private int j = 0;*/
    
        private Singleton07() {}
    
        // 静态内部类只有等到需要用到才会加载,在加载过程中JVM会获取一个锁,不会出现线程安全问题,且只加载一次
        /*静态内部类有一个局限性,只能访问外部类静态的变量,非静态的无法访问*/
        private static class Inner {
            private static final Singleton07 INSTANCE = new Singleton07();
    
            /*private void test() {
                i += 1;
                // j += 1; // 无法访问
            }*/
        }
    
        public static Singleton07 getInstance() {
            return Inner.INSTANCE;
        }
    
    }
    
    class Test07 {
        public static void main(String[] args) {
            Singleton07 s1 = Singleton07.getInstance();
            Singleton07 s2 = Singleton07.getInstance();
            System.out.println(s1 == s2); // true
        }
    }

    枚举实现单例:枚举本身已经实现了线程安全

    /**
     * 枚举实现单例
     *
     * 枚举实际上是一种多例的模式,如果我们直接定义一个实例就相当于单例了
     */
    public enum Singleton08 {
        INSTANCE;
    
        public Singleton08 getInstance() {
            return INSTANCE;
        }
    }
    
    class test08 {
    
        public static void main(String[] args) {
            Singleton08 s1 = Singleton08.INSTANCE.getInstance();
            Singleton08 s2 = Singleton08.INSTANCE.getInstance();
            System.out.println(s1 == s2); // true
        }
    
    }
  • 相关阅读:
    Linux内核设计与实现 总结笔记(第五章)系统调用
    Linux内核设计与实现 总结笔记(第四章)进程调度
    Linux内核设计与实现 总结笔记(第三章)进程
    Linux内核设计与实现 总结笔记(第二章)
    4412 移植x264并且YUV422转x264
    4412 使用usb摄像头拍照YUYV格式
    LDD3 第15章 内存映射和DMA
    LDD3 第13章 USB驱动程序
    ldd3 第12章 PCI驱动程序
    4412 移植mpu9250尝试
  • 原文地址:https://www.cnblogs.com/roadlandscape/p/12894259.html
Copyright © 2011-2022 走看看