java笔记----单例模式


前言

单例模式在很多面试题都出现过,单例模式能够保证一个类仅有唯一的实例,并提供一个全局访问点。而不用想要每个对象的时候就去new一个,这样浪费资源和空间


一、单例模式是什么?

平时使用的软件中,例如 回收站、线程池、文件系统等,都只有一个实例,这些都是单例模式的典型应用。
  
单例模式:确保某个类只有一个实例,并提供一个全局访问点来访问这个实例。
单例模式有三个要点:
  1. 某个类只能有一个实例
  2. 必须自行创建这个实例
  3. 必须自行向整个系统提供这个实例。
以上三个要点提示着我们的代码编写需要注意,构造函数必须私有,否则在其他类中便可以调用构造函数创建实例,难以保证实例的唯一性

二、饿汉模式

1、饿汉定义

为什么要叫饿汉呢?这里可以理解为很饿,所以迫不及待地在类加载的时候就创建一个实例对象

//饿汉模式:(线程安全)
class Singleton1 {
    // 静态私有成员变量
    private static Singleton1 instance = new Singleton1();
    // 私有构造函数
    private Singleton1() {
    }
        // 静态公有工厂方法,返回唯一实例
    public static Singleton1 getInstance() {
        return instance;
    }
}

2、为什么说饿汉模式是线程安全的呢?

答:因为在每次类加载的开始,该对象的实例就被创建了,线程要访问该对象一开始就拿到了这个唯一的对象,所以它是线程安全的

三、懒汉模式

1、懒汉定义

和饿汉相对应,懒汉十分的懒,直到有线程需要访问该对象的时候,他才去判断是否已经有对象存在,如果没有,才再去创建对象

// 懒汉模式:(线程不安全,需要通过双重检查锁定机制控制)
class Singleton2 {
    // 静态私有成员变量
    private static Singleton2 instance = null;
    // 私有构造函数
    private Singleton2() {
    }
    // 静态公有工厂方法,判断成员变量是否为空,不为空则实例化
    public static Singleton2 getInstance() {
        if(instance == null)
            instance = new Singleton2();
        return instance;
    }
}

2、为什么说懒汉模式是线程不安全的呢?

如果有两个线程AB要访问这个对象,拿对象的时候在if(instance == null) 前,实例都没有被创建,那么 A 会得到 true 的结果,但是此时调度算法选择 B 线程运行,那么当 B 执行 到 if(instance == null) 时得到的也是 true,z这样两个线程都会执行 instance = new Singleton2(); 从而创建了两个实例。

3、双重检查锁定机制

为了将懒汉式变为线程安全的模式,就要采用双重检查锁定机制,该机制的原理是加一个同步锁(类锁),就可以防止多个线程同时创建对象,因为他们现在是互斥的访问

/*
* 懒汉式,双重检查锁定机制
* */
class Singleton3 {
    // 私有静态成员变量
    private static volatile Singleton3 instance = null;
    // 私有构造函数
    private Singleton3() {
    }
    // 共有静态工厂方法
    public static Singleton3 getInstance() {
    // 判断 instance 是否为空,为空->加锁,创建实例(为了进程安全,再次判断),不为空->返回实例
        if(instance == null) {
            synchronized (Singleton3.class) {
                if(instance == null)
                    instance = new Singleton3();
            }
        }
        return instance;
    }
}

四、饿汉式与懒汉式的优缺点

饿汉模式不需要考虑线程安全问题,调用速度和访问速度优于懒汉模式,但是由于它不管是否被调用都会提前创建类的实例,所以资源利用效率比较低,系统加载时间比较长。

懒汉模式实现了延迟加载,但是需要克服多个线程同时访问的问题,需要通过双重检查锁定机制进行控制,导致系统性能受到一定影响。

总结

本章的内容是java单例模式的实现,为什么要使用单例模式可以参考

https://blog.csdn.net/love_java_cc/article/details/52161884

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

冰棍hfv

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值