Java设计模式3:单例模式

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/weixin_37591536/article/details/82895468

前言:

单例模式是一种常用的软件设计模式,在我们项目与所用到的各种框架中会经常见到。本文就详细介绍下,几种单例模式的常见写法。

一、单例模式:

单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例。在计算机系统中,线程池、缓存、日志对象、对话框、打印机、显卡的驱动程序对象常被设计成单例。这些应用都或多或少具有资源管理器的功能。每台计算机可以有若干个打印机,但只能有一个Printer Spooler,以避免两个打印作业同时输出到打印机中。每台计算机可以有若干通信端口,系统应当集中管理这些通信端口,以避免一个通信端口同时被两个请求同时调用。总之,选择单例模式就是为了避免不一致状态。

二、单例模式特点:


1、单例类只能有一个实例。
2、单例类必须自己创建自己的唯一实例。
3、单例类必须给所有其他对象提供这一实例。

单例模式保证了全局对象的唯一性,比如系统启动读取配置文件就需要单例保证配置的一致性。

下面就介绍下单例模式的三种写法,饿汉式、懒汉式、双重检索式。其他的静态内部类的方式、静态代码块的方式、enum枚举的方式也都可以,不过异曲同工,这里只介绍前面三种比较常见的。

第一种:饿汉式

顾名思义,饿汉式,就是使用类的时候不管用的是不是类中的单例部分,都直接创建出单例类,看一下饿汉式的写法:

/**
 * <pre>
 *    @author : orange
 *    @e-mail : [email protected]
 *    @time   : 2018/9/29 11:15
 *    @desc   : 饿汉式单例
 *    @version: 1.0
 * </pre>
 */
public class HungrySingleton {

    private static HungrySingleton hungrySingleton = new HungrySingleton();

    private HungrySingleton(){}

    public static HungrySingleton getHungrySingleton(){
        return hungrySingleton;
    }
}

这就是饿汉式单例模式的写法,也是一种比较常见的写法。这种写法会不会造成竞争,引发线程安全问题呢?答案是不会。可能有人会觉得奇怪:

代码的第3行(private static HungrySingleton hungrySingleton = new HungrySingleton();),CPU执行线程A,实例化一个HungrySingleton,没有实例化完,CPU就从线程A切换到线程B了,线程B此时也实例化这个HungrySingleton,然后HungrySingleton被实例化出来了两次,有两份内存地址,不就有线程安全问题了吗?

没关系,我们完全不需要担心这个问题,JDK已经帮我们想到了。Java虚拟机2:Java内存区域及对象,文中可以看一下对象创建这一部分,没有写得很详细,其实就是"虚拟机采用了CAS配上失败重试的方式保证更新更新操作的原子性和TLAB两种方式来解决这个问题"。

第二种:懒汉式

只有当单例类用到的时候才会去创建这个单例类,看一下懒汉式的写法:

扫描二维码关注公众号,回复: 3474790 查看本文章
/**
 * <pre>
 *    @author : orange
 *    @e-mail : [email protected]
 *    @time   : 2018/9/29 11:24
 *    @desc   : 懒汉式单例  线程不安全,很少用
 *    @version: 1.0
 * </pre>
 */
public class LazySingleton {

    private static LazySingleton singleton = null;

    private LazySingleton(){}

    public static LazySingleton getSingleton(){

        if(null == singleton){
            singleton =  new LazySingleton();
        }
        return singleton;
    }
}

懒汉式单例模式这种写法在多线程环境下会产生多个single对象,所以是线程不安全的,一般都很少用。下面的双重检索模式其实就是对这种线程不安全的改造。

 

第三种:双重检索式

/**
 * <pre>
 *    @author : orange
 *    @e-mail : [email protected]
 *    @time   : 2018/9/29 11:28
 *    @desc   : 双重检索方式,线程安全
 *    @version: 1.0
 * </pre>
 */
public class DoubleCheckLockSingleton {

    private static DoubleCheckLockSingleton singleton = null;

    private DoubleCheckLockSingleton(){}

    public static DoubleCheckLockSingleton getSingleton(){

        if(null == singleton){
            synchronized (DoubleCheckLockSingleton.class){
                if(null == singleton){
                    singleton =  new DoubleCheckLockSingleton();                }
            }
        }

        return singleton;
    }

}


总结:

单例模式的好处

作为一种重要的设计模式,单例模式的好处有:

1、控制资源的使用,通过线程同步来控制资源的并发访问

2、控制实例的产生,以达到节约资源的目的

3、控制数据的共享,在不建立直接关联的条件下,让多个不相关的进程或线程之间实现通信

猜你喜欢

转载自blog.csdn.net/weixin_37591536/article/details/82895468