【小家java】细说java中设计模式---单例模式

1、概述

作为23中设计模式之一—单例模式。是我们最耳熟能详的一种设计模式,也是被广大coder所掌握的一种设计模式,但是你真的掌握了单例模式吗?能保证没有bug吗?
Java中单例模式是一种广泛使用的设计模式。单例模式的主要作用是保证在Java程序中,某个类只有一个实例存在。一些管理器控制器常被设计成单例模式。
单例模式有很多好处,它能够避免实例对象的重复创建,不仅可以减少每次创建对象的时间开销,还可以节约内存空间(比如spring管理的无状态bean);能够避免由于操作多个实例导致的逻辑错误。如果一个对象有可能贯穿整个应用程序,而且起到了全局统一管理控制的作用,那么单例模式也许是一个值得考虑的选择。
单例模式有很多种写法(7种),大部分写法都或多或少有一些不足。下面将分别对这几种写法进行介绍。

2、栗子

1、懒汉(线程不安全):

public class Singleton {  
    private static Singleton instance;  
    private Singleton (){}  //私有构造函数

    public static Singleton getInstance() {  
    if (instance == null) {  
        instance = new Singleton();  
    }  
    return instance;  
    }  
}  

这种写法lazy loading(懒加载)很明显,但是一看就知道,存在线程安全问题,不解释 禁止这样书写。
2、懒汉(线程安全):

public class Singleton {  
    private static Singleton instance;  
    private Singleton (){}  
    public static synchronized Singleton getInstance() {  
    if (instance == null) {  
        instance = new Singleton();  
    }  
    return instance;  
    }  
}  

显然加了个synchronized来保证线程安全,but,效率太低了,毕竟99.99%的情况下是不需要同步的,有点用力过猛
3、饿汉

public class Singleton {  
    private static Singleton instance = new Singleton();  
    private Singleton (){}  
    public static Singleton getInstance() {  
    return instance;  
    }  
}  

这种基于classloder机制避免了多线程的同步问题,初始化的时候就给装载了。但是现在,没有懒加载的效果了
4、饿汉(变种):

public class Singleton {  
    private static Singleton instance = null;  
    static {  
      instance = new Singleton();  
    }  
    private Singleton (){}  
    public static Singleton getInstance() {  
    return this.instance;  
    }  
} 

第三种方式差不多,都是在类初始化即实例化instance。
5、静态内部类:

public class Singleton {  
    private static class SingletonHolder {  
    private static final Singleton INSTANCE = new Singleton();  
    }  
    private Singleton (){}  
    public static final Singleton getInstance() {  
    return SingletonHolder.INSTANCE;  
    }  
}  

第三种和第四种方式是只要Singleton类被装载了,那么instance就会被实例化(没有达到lazy loading效果),而这种方式是Singleton类被装载了,instance不一定被初始化。因为SingletonHolder类没有被主动使用,只有显示通过调用getInstance方法时,才会显示装载SingletonHolder类,从而实例化instance。这个时候,这种方式相比第三和第四种方式就显得很合理。
6、双重校验锁(这个相对来说比较复杂):

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

使用到了volatile机制。这个是第二种方式的升级版,俗称双重检查锁定。既保证了效率,又保证了安全。
7、枚举:

public enum Singleton {  
    INSTANCE;  
    public void whateverMethod() {  
    }  
}  

这种方式是Effective Java作者Josh Bloch 提倡的方式,它不仅能避免多线程同步问题,而且还能防止反序列化重新创建新的对象,可谓是很坚强的壁垒啊。所以这种写法,其实是十分推荐的

3、使用场景

到处都是

4、最后

本文总结了7种Java中实现单例的方法,其中前两种都不够完美,双重校验锁和静态内部类的方式可以解决大部分问题,平时工作中使用的最多的也是这两种方式。所以,个人推荐枚举的方式,哈哈哈哈

—-题后语—-

我的微信公众号也会持续推送技术干货,欢迎下方二维码扫码关注获取。
这里写图片描述
更多内容持续更新中,欢迎关注我的博客!
有任何问题,可以跟我留言讨论,欢迎指正,不胜感激。
有任何疑问,亦可扫码向我提我哟~

猜你喜欢

转载自blog.csdn.net/f641385712/article/details/80396026
今日推荐