设计模式之单例模式

一,前言

​ 单例模式在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;  
    }  
}

七,总结

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

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

感谢阅读!

posted @ 2019-09-16 20:29  奋进的小样  阅读(195)  评论(0编辑  收藏  举报