• 设计模式之单例模式


    一,前言

    ​ 单例模式在23中设计模式中是最为基础的一种,并且使用范围非常广泛,属于设计模式中的创建型模式。

    什么是单例:指某一个类只允许存在一个实例对象。

    单例模式特点:

    • 单例只允许一个实例存在,减少资源浪费。
    • 对于频繁创建和销毁的对象,单例模式可以很好的解决,提高系统的性能。
    • 单例类只能自己提供自己的实例对象,因为单例模式构造方法是私有的。
    • 对外提供唯一的全局访问方式。

    单例模式的实现:懒汉式,饿汉式。

    二,饿汉式

    ​ 饿汉式单例模式,字面理解就是很饿很急的感觉。因此这种单例对象就是即时创建,类初始化完成时该对象就已经创建完成。使用起来很方便,但是很容易产生较多的垃圾对象,同时浪费内存空间,下面请看示例代码:

    public class Singleton {
        private static Singleton singleton = new Singleton();
        // 私有化无参构造
        private Singleton(){}
        // 对外提供访问对象的接口
        public static Singleton getSingleton(){
            return singleton;
        }
    }
    

    ​ 饿汉式是线程安全的,在类加载时就已经创建完成。

    三,懒汉式

    ​ 懒汉式的创建方式与饿汉式相反,即什么时候用到就什么时候创建,典型的懒加载机制。因此在多线程情况下是线程不安全的,容易重复创建对象,违背了单例模式的原则。

    public class Singleton2 {
        private static Singleton2 singleton2;
        // 私有构造方法
        private Singleton2() {}
        public static Singleton2 getInstance() {
            // 判断如果不存在,则创建
            if (singleton2 == null) {
                singleton2 = new Singleton2();
            }
            return singleton2;
        }
    }
    

    ​ 对于懒加载线程不安全问题,可以使用synchronized,双重检验锁。

    四,synchronized

    ​ synchronized可以保证线程安全,但是我们都知道,使用这种方式效率是很低的,因为程序会不断判断锁是否存在,判断获取锁,释放锁。(不推荐使用)

    public class Singleton {
        private static Singleton instance;
        private Singleton (){}
        // 同步方法
        public static synchronized Singleton getInstance() {
            if (instance == null) {
                instance = new Singleton();
            }
            return instance;
        }
    }
    

    五,双重检验锁

    ​ 这里先说明以下,双重检验锁不是指使用两次synchronized关键字,而是在锁之前先判断一次单例对象是否已经存在,如果存在则直接获取。不存在再进入同步方法中,但是静态成员变量需要被volatile修饰,防止发生指令重排。

    public class Singleton3 {  
        private volatile static Singleton3 singleton;  
        private Singleton3 (){}  
        public static Singleton3 getSingleton() {  
            if (singleton == null) {  
                synchronized (Singleton3.class) {  
                    if (singleton == null) {  
                        singleton = new Singleton3();  
                    }  
                }  
            }  
            return singleton;  
        }  
    }
    

    六,静态内部类

    ​ 静态内部类,这种内部类与其外部类之间并没有先后级别,加载外部类的时候,并不会同时加载静态内部类,而只有调用的时候才会进行加载,此时便创建出单例对象。那么对于线程安全问题来说,因为使用静态初始化方式,所以在JVM中就会自动保证线程安全问题。

    public class Singleton4 {  
        private static class SingletonMethod {  
            private static final Singleton4 instance = new Singleton4();  
        }  
        private Singleton4 (){} 
        
        public static final Singleton4 getInstance() {  
            return SingletonMethod.instance;  
        }  
    }
    

    七,总结

    ​ 对于以上几种方式,要根据实际业务进行选择,但通常情况下饿汉式的使用会多一些,但这不绝对。

    ​ 以上内容均是自主学习总结,如有不适之处欢迎留言指正。

    感谢阅读!

  • 相关阅读:
    POJ3678 KATU PUZZLE
    poj3321(codevs1228)苹果树
    codevs 1955 光纤通信 USACO
    codevs 1027 姓名与ID
    codevs 1051 接龙游戏
    洛谷 P1717 钓鱼
    codevs 1062 路由选择
    洛谷 P1083 借教室
    codevs 2596 售货员的难题
    Vijos 1053 easy sssp
  • 原文地址:https://www.cnblogs.com/fenjyang/p/11529712.html
Copyright © 2020-2023  润新知