设计模式——单例模式

本文详细探讨了单例模式的概念、作用及其实现方式,包括线程不安全、线程安全的饿汉式和懒汉式单例。通过对不同实现方式的分析,重点介绍了线程安全的懒汉式单例,它在保证多线程环境下安全的同时,避免了性能影响。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

欢迎转载,请附出处:
http://blog.csdn.net/as02446418/article/details/47952947

单例模式(Singleton)

首先来明确一个问题,那就是在某些情况下,有些对象,我们只需要一个就可以了,

比如,一台计算机上可以连好几个打印机,但是这个计算机上的打印程序只能有一个,

这里就可以通过单例模式来避免两个打印作业同时输出到打印机中,

即在整个的打印过程中我只有一个打印程序的实例。

简单说来,单例模式(也叫单件模式)的作用就是保证在整个应用程序的生命周期中,

任何一个时刻,单例类的实例都只存在一个(当然也可以不存在)。

单例模式的结构图

这里写图片描述

从上面的类图中可以看出,在单例类中有一个构造函数 Singleton ,

但是这个构造函数却是私有的(前面是“ - ”符号),

然后在里面还公开了一个 GetInstance()方法,

通过上面的类图不难看出单例模式的特点,从而也可以给出单例模式的定义

单例模式保证一个类仅有一个实例,同时这个类还必须提供一个访问该类的全局访问点。

下面来看代码:

public class Singleton1 {
    private static Singleton1 instance;
    private Singleton1(){
        System.out.println("我是线程不安全的饿汉singleton");
    }

    public static Singleton1 getSingleton1(){
        if (instance==null) {
            instance = new Singleton1();
        }

        return instance;
    }


}

如上面代码所示,这种写法是最不推荐的,也是因为它的线程不安全,我们来看一下测试代码和运行结果:

线程不安全的singleton

public class SingletonTest {
    public static void main(String[] args){

        for (int i = 0; i < 100; i++) {
            new Thread(new Runnable() {

                @Override
                public void run() {
                    Singleton1.getSingleton1();

                }
            }).start();
        }

    }
}

这里写图片描述

这里new了三个singleton,在多线程环境下可能存在多个线程判断instance==null,所以会分别new出自己的instance,这显然违背了单例模式的初衷。

接下来我们换种写法:

线程安全的饿汉singleton

public class Singleton2 {
    private static Singleton2 instance = new Singleton2();
    private Singleton2(){
        System.out.println("我是线程安全的饿汉singleton");
    }

    public static Singleton2 getSingleton1(){

        return instance;
    }

}

下面是运行结果:
这里写图片描述

为什么说是饿汉的singleton,因为如上面代码所示,在用到示例instance之前就已经把它初始化好了,虽然这里是线程安全的,但是也会影响性能,所以我们来看第三种singleton。

线程安全的懒汉singleton

public class Singleton {
    private Singleton(){
        System.out.println("我是线程安全的singleton");
    }

    private static class singletonHolder{
        private final static Singleton instance = new Singleton();
    } 


    public static Singleton getSingleton(){
        return singletonHolder.instance;
    }

}

下面是运行结果:
这里写图片描述

如上述代码所示,这里用到了singletonHolder这个内部类,这个内部类只会在singletonHolder.instance中用到,也就是用的时候才会初始化,故称为懒汉singleton,这样既解决了多线程下不安全的问题,同时也解决了提前初始化影响的性能问题,所以是最推荐的一种写法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值