大话设计模式(三)--单例模式(八种)

本文深入探讨单例模式的实现方式,包括饿汉式、懒汉式等不同类型的单例模式,以及它们在效率、线程安全性和内存使用方面的特点。同时,文章对比了静态内部类和枚举实现单例模式的优势。

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

单例模式

单例模式应该是程序员最常遇到的设计模式
单例模式会阻止其他对象实例化其自己的单例对象的副本,从而确保所有对象都访问唯一实例。

一饿汉式 (两种)

顾名思义 系统饿了 上来就吃
也即JVM在加载这个类时就完成了单例的创建,JVM也保证了它时线程安全的 效率也高
不足:在类加载时就完成实例化,没有懒加载的效果,如果从始至终没有使用过这个实例会造成内存浪费

public class Singleton {
    public static final Singleton instance = new Singleton();

    private Singleton(){

    }

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

    }

}

二懒汉式 (四种)

顾名思义 太懒了 你用到我的时候我再实例化

1.懒加载模式   效率高
2.线程不安全  一个JVM种可能存在多个实例  
public class Singleton {
    private static  Singleton instance =null;

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

    private Singleton(){

    }

}
1.这种方法与上面唯一的不同是加了synchronized 同步锁
2.懒加载模式  锁粒度大 效率低
3.线程安全
public class Singleton {
    private static  Singleton instance =null;

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

    private Singleton(){

    }

}
1.懒加载模式   效率较高
2.线程不安全
public class Singleton {
    private static  Singleton instance =null;

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

    private Singleton(){

    }

}
1.懒加载模式   效率高
2.极端情况下线程不安全  
public class Singleton {
    private static  Singleton instance =null;

    public  static Singleton getInstance(){
        if (instance == null){
            synchronized(Singleton.class){
                if (instance == null){
                    instance = new Singleton();//这一步可能导致线程不安全
                    原因 是因为无法保证有序性
                     我们正常理解的new 一个对象 分为三步
                     1.JVM堆内存种开辟一块空间
                     2.填充对象属性的值
                     3.将instance 指针指向该区域  
                     但是在多线程环境中CUP会对指令重排序 执行顺序可能变为 132
                     这种情况下当此线程执行完13两步操作 该实例对象已经不为null,别的线程就可能拿到没有初始化过的实例,惊醒操作  可以用volatile 保证此有序性
                }
            }
        }
        return instance;
    }

    private Singleton(){

    }
}
双重检查 懒加载 线程安全  高效  
完美?  不不不 以上这几种 还都能用反射和序列化创建多个对象
public class Singleton {
    private volatile static  Singleton instance =null;

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

    private Singleton(){

    }

}

三静态内部类

静态内部类    懒加载  高效 线程安全    但是 还是可以用反射和序列化获取
public class Singleton {
    private static class SingletonInstance{
        private static Singleton instance = new Singleton();
    }

    public static Singleton getInstance(){
        return SingletonInstance.instance;
    }
    
    private Singleton(){
        
    }

}

四枚举

枚举实现  推荐使用  安全 高效  JVM保证反射和序列化也无法创建多个实例
public enum  Singleton {

    instance;
    
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值