单例模式 (懒汉,饿汉,双重校验锁)

本文深入探讨了单例模式的概念及其实现方式,包括懒汉式、饿汉式和双重校验锁等不同方法的特点与应用场景,并分析了它们的线程安全性。

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

单例模式

什么是单例模式?

 单例保证一个对象JVM中只能有一个实例,常见单例懒汉式、饿汉式

 什么是懒汉式,就是需要的才会去实例化,线程不安全。

 什么是饿汉式,就是当class文件被加载的时候,初始化,天生线程安全。

 懒汉式 代码 

package designpatterns23.singleton;

/**
 * 单例模式的作用:保证一个类在项目中有且只能有一个实例
 * 在调用的时候在去初始化天生线程是不安全的
 * Created by lizhen on 2018/1/30.
 */
public class Singleton {
    private static Singleton singleton;

    /**
     * 构造方法私有化,防止在外部进行new
     */
    private Singleton() {

    }

    /**
     * 此方法是线程不安全的
     * 提供一个对外的方法获取singleton的实例
     *
     * @return singleton实例
     */
    public static Singleton getSingleton() {
        if (null == singleton) {
            singleton = new Singleton();
        }
        return singleton;
    }

   }

饿汉式线程 安全代码  
package designpatterns23.singleton;

/**
 * 单例模式的作用:保证一个类在项目中有且只能有一个实例
 * 在调用的时候在去初始化天生线程是不安全的
 * Created by lizhen on 2018/1/30.
 */
public class Singleton {
    private static Singleton singleton;

    /**
     * 构造方法私有化,防止在外部进行new
     */
    private Singleton() {

    }

   

    /**
     * 懒汉式修改为线程安全的方法
     * 缺点:加入锁影响效率
     *
     * @return
     */
    public static Singleton getSingleton2() {
        if (null == singleton) {
            //第一次同时进入判断的有可能有两个线程,所以在此处加入同步锁,相对于在方法上加入锁,提高了效率
            synchronized (Singleton.class) {
                singleton = new Singleton();
            }
        }
        return singleton;
    }

  
}




饿汉式 代码
package designpatterns23.singleton;

/**
 * 单例模式之饿汉式
 * 在加载的时候就已经初始化了,天生线程安全
 * Created by lizhen on 2018/1/30.
 */
public class Singleton1 {
    /**
     * 利用静态的关键字,类一加载便去初始化此类
     */
    private static Singleton1 singleton1 = new Singleton1();

    /**
     * 构造方法私有化
     */
    private Singleton1 (){

    }

    /**
     * 提供一个对外获取此类的方法
     * @return 此类的实例
     */
    public  static  Singleton1 getSingleton1(){
        return  singleton1;
    }
}

 双重校验锁
关于volatile关键字的使用,我有一篇专门关于讲解这个关键字的博客以及关于java内存模型的知识,大家可以看一下这一篇
http://mp.blog.youkuaiyun.com/postedit/79043326

package designpatterns23.singleton;

/**
 * 单例模式的作用:保证一个类在项目中有且只能有一个实例
 * 单例模式之懒汉式 ----双重校验锁
 * 在调用的时候在去初始化天生线程是不安全的
 * Created by lizhen on 2018/1/30.
 */
public class Singleton {
   
    /**
     * 构造方法私有化,防止在外部进行new
     */
    private Singleton() {

    }

    /**
     * 一般我们用双重校验锁的时候需要使用volatile关键字
     * volatile 是关于java内存模型相关的知识,只能保证可见性,但不能保证原子性
     */
   
private volatile static Singleton singleton;
/** * 双重校验锁模式 * * @return singleton 实例; */ public static Singleton getSingleton3() { if (singleton == null) { synchronized (Singleton.class) { /** * 为什么还要重新判断一下呢? * 因为同时等待锁的有可能有多个线程,当第一线程释放锁之后,后面的线程得到锁就可以进入这个方法 * 这时如果不进行判断的话很有可能就会创建多个实例. */ if (singleton == null) { singleton = new Singleton(); } } } return singleton; }}
我们看一下效果

### 单例模式中的懒汉式与饿汉式 #### 饱和度对比 饿汉式会在类装载时就完成实化,无论后续是否会实际使用这个对象。而懒汉式则是在第一次被请求时才进行实化操作[^1]。 #### 性能影响 由于懒汉式的首次访问会有一定的初始化开销,因此在初次获取实时可能会有短暂的性能延迟;然而一旦实创建完毕后,其表现与其他任何形式无异。相比之下,饿汉式虽然一开始就完成了实化过程,但如果程序运行期间从未用到此,则会造成资源浪费[^3]。 #### 线程安全性考量 对于多线程环境下的应用来说,简懒汉实现在并发场景下存在安全隐患——多个线程可能几乎同时发现`lazyMan==null`并各自创建新的实,从而破坏了原则。为了防止这种情况发生,可以通过加锁机制来确保线程安全,比如采用同步方法或者更高效的双重检查锁定(Double-Checked Locking)[^5]。 #### 编码实践示 ##### 饿汉式实现 ```java public class Singleton { // 类加载即已完成实化 private static final Singleton instance = new Singleton(); // 私有构造函数阻止外部new对象 private Singleton(){} // 提供全局访问点 public static Singleton getInstance(){ return instance; } } ``` ##### 懒汉式简(非线程安全) ```java public class LazySingleton{ private static LazySingleton instance; private LazySingleton(){} public static LazySingleton getInstance(){ if(instance == null){ instance = new LazySingleton(); } return instance; } } ``` ##### 懒汉式改进版(线程安全, 使用synchronized关键字) ```java public class ThreadSafeLazySingleton{ private static volatile ThreadSafeLazySingleton uniqueInstance; private ThreadSafeLazySingleton(){} /** * 加入volatile修饰符以及synchronized关键字保证线程安全, * 同时减少不必要的同步带来的性能损耗. */ public static synchronized ThreadSafeLazySingleton getInstance(){ if(uniqueInstance == null){ uniqueInstance = new ThreadSafeLazySingleton(); } return uniqueInstance; } } ``` ##### 懒汉式优化版本(双重校验锁) ```java public class DoubleCheckLockingSingleton { private static volatile DoubleCheckLockingSingleton uniqueInstance; private DoubleCheckLockingSingleton() {} public static DoubleCheckLockingSingleton getInstance() { if (uniqueInstance == null) { // 第一次检查 synchronized (DoubleCheckLockingSingleton.class) { if (uniqueInstance == null) { // 第二次检查 uniqueInstance = new DoubleCheckLockingSingleton(); } } } return uniqueInstance; } } ```
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值