设计模式----单例设计模式

本文详细介绍了单例设计模式的概念及其在Java中的8种实现方式,包括懒汉式、饿汉式等,并分析了每种方式的优点和缺点,帮助读者理解如何在不同场景下选择合适的单例模式。

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

单例设计模式

github :   https://github.com/zhang-shoukang/design-pattern

单例设计模式在面试的被问到的几率太大了,大多数问的都是,你能说粗来多少种单例设计模式。

如果你只能说出来懒汉式,饿汉式,估计面试官对你也就彻底失望了。

如果你能说出来四五种,那估计面试官对你印象还不错。

但是如果你能说出来七八种,那估计这次面试就妥了。

 

1.是什么?

单例对象(Singleton)是一种常用的设计模式。在Java应用中,单例对象能保证在一个JVM中,该对象只有一个实例存在。

 

2.这种设计模式的好处:

1、某些类创建比较频繁,对于一些大型的对象,这是一笔很大的系统开销。

2、省去了new操作符,降低了系统内存的使用频率,减轻GC压力。

3、有些类如交易所的核心交易引擎,控制着交易流程,如果该类可以创建多个的话,系统完全乱了。(比如一个军队出现了多个司令员同时指挥,肯定会乱成一团),所以只有使用单例模式,才能保证核心交易服务器独立控制整个流程。

 

3.   8种不同的单例设计模式

  3.1

//懒汉式

/**
 * 好处: 用到改实例的时候,才会实例化该对象,不会浪费资源
 * 坏处:非线程安全,多线程环境下,会创建多个实例。
  */
@NotThreadSafe
@NotRecommend
public class Singleton01 {
    private static Singleton01 singleton01;
    private Singleton01(){};
    public static Singleton01 getInstance(){
        if (singleton01==null){           //point
            singleton01 =  new Singleton01();
        }
        return singleton01;
    }
}

3.2

//饿汉式
/**
 * 好处:线程安全,从始至终只有一个实例
 * 坏处:丢失了延迟实例化,资源可能浪费
 */
@ThreadSafe
@NotRecommend
public class Singleton02 {
    private Singleton02 singleton02 = new Singleton02();
    private Singleton02(){}
    public Singleton02 getSingleton02() {
        return singleton02;
    }
}

3.3

//懒汉式 加锁

/**
 * 好处:通过加锁保证了线程安全
 * 坏处:因为加锁,带来的性能问题 (一次只能有一个线程被处理)
 */
@ThreadSafe
@NotRecommend
public class Singleton03 {
    private Singleton03 singleton03 =null;
    private Singleton03(){};

    public synchronized Singleton03 getSingleton03() {
        if (singleton03==null){
            singleton03=new Singleton03();
        }
        return singleton03;
    }
}

3.4

//双重校验锁

/**
 *优点:保证了单例,和延迟加载
 *缺点:但是有可能会出现安全问题。
  */

/**
 * 对象初始化顺序:
 * 1. memory= allocate()  分配对象的内存空间
 * 2.constructor Instance  对象初始化
 * 3. instance=memory  设置instance 指向刚刚分配的内存
 *
 * 但是多线程情况下,会出现jdk和jvm的优化,有可能会发生指令重排
 * 顺序变为如下:
 * 1. memory= allocate()  分配对象的内存空间
 * 3. instance=memory  设置instance 指向刚刚分配的内存
 * 2.constructor Instance  对象初始化
 *
 * 故障重演:
 * 线程A: 执行到  singleton04=new Singleton04();   因为发生指令重拍,出现了上面的顺序。
 * 线程B: 执行到  第一个 if (singleton04==null){   发现singleton04 不为null  ,return singleton04
 * 程序其他地方如果用到了返回的singleton04 ,就会报NullPointException
 */
@NotThreadSafe
@NotRecommend
public class Singleton04 {
    private Singleton04(){}
    private static Singleton04 singleton04=null;
    public static Singleton04 getInstance(){
        if (singleton04==null){
            synchronized (Singleton04.class){
                if (singleton04==null){
                    singleton04=new Singleton04();
                }
            }
        }
        return singleton04;
    }
}

3.5

//双重校验锁 + validate  防止指令重排


/**
 *优点: 加入validate 避免指令重排,线程安全
 * 缺点:还是加锁
  */
@ThreadSafe
@NotRecommend
public class Singleton05 {
    private Singleton05(){}
    private volatile static Singleton05 singleton05=null;
    public static Singleton05 getInstance(){
        if (singleton05==null){
            synchronized (Singleton05.class){
                if (singleton05==null){
                    singleton05=new Singleton05();
                }
            }
        }
        return singleton05;
    }
}

3.6

 //饿汉模式
//单例实例在类装载时进行创建

/**
 * 优点:在类装载的时候进行一次初始化,线程安全
 * 缺点:提前初始化,可能会浪费资源(如果一直没用到)
 */
@ThreadSafe
@NotRecommend
public class Singleton06 {

    private Singleton06(){}
    public static Singleton06 singleton06=null;
    static {
        singleton06 = new Singleton06();
    }
    public static Singleton06 singleton06(){
        return singleton06;
    }
}

3.7

//静态内部类实现

/**
 * 优点:当Singleton07加载的时候,SingletonHoler不会加载进入内存,只有当真正调用getInstance方法,才会加载,初始化INSTANCE
 * 而且可以达到延迟加载的目的,而且由虚拟机提供了对线程安全的支持。
 */
@ThreadSafe
@Recommend
public class Singleton07 {
    private Singleton07(){}

    private static class SingletonHoler{
        private static final Singleton07 INSTANCE = new Singleton07();
    }
    public static Singleton07 getInstance(){
        return SingletonHoler.INSTANCE;
    }

}

3.8

//枚举方式

/**
 * 优点: 最安全
 * // JVM保证这个方法绝对只调用一次
 //Singleton() {
 //singleton = new SingletonExample7();
 //}
 */
@ThreadSafe
@Recommend
public class Singleton08 {
    private Singleton08(){}
    public static Singleton getInstance(){
        return Singleton.INSTANCE.getSingleton();
    }
    private enum Singleton{
        INSTANCE;
        public Singleton singleton;

        public Singleton getSingleton() {
            return singleton;
        }
    }
}

4.总结

单例设计模式,种类繁多,用的时候可以根据需要选择。

JDK种具体实例,如 java.lang.Runtime#getRuntime()。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值