单例模式

本文介绍了单例模式的六种实现方法,包括懒汉式(线程不安全与线程安全)、饿汉式、双检锁/双重校验锁、登记式/静态内部类以及枚举。强调了使用枚举实现单例模式的安全性和简洁性。

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

在这里插入图片描述
单例模式实现方式:
1、懒汉式,线程不安全

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

2、懒汉式,线程安全

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

3、饿汉式

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

4、双检锁/双重校验锁

public class Singleton {  
    private volatile static Singleton singleton;  
    private Singleton (){}  
    public static Singleton getSingleton() {  
    if (singleton == null) {  
        synchronized (Singleton.class) {  
        if (singleton == null) {  
            singleton = new Singleton();  
        }  
        }  
    }  
    return singleton;  
    }  
}

5、登记式/静态内部类

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

6、枚举

public enum Singleton {  
    INSTANCE;  
    public void whateverMethod() {  
    }  
}

直接通过Singleton.INSTANCE.whateverMethod())的方式调用即可。方便、简洁又安全。

为什么要判断两次?

class SingletonTwo{	
	/* 持有私有静态实例,防止被引用,此处赋值为null,目的是实现延迟加载 */ 
	private static SingletonTwo instance = null;	
	/* 私有构造方法,防止被实例化 */
	private SingletonTwo(){
		
	}
	
	public static SingletonTwo getInstance() {  
	//位置1
        if (instance == null) {  
            //位置2
            synchronized (instance) {  
            	//位置3
                if (instance == null) {  
                    //位置4
                    instance = new SingletonTwo();  
                }  
            }  
        }  
        return instance;  
    }  
}
假设线程A和B作为第一批调用者同时或几乎同时调用静态工厂方法getInstance。
1)因为A和B是第一批调用者,当它们进入静态工厂方法时,instance变量是null。因此它们几乎同时到达 位置2。
2)  假设A线程先进入 synchronized (instance),到达位置3,这时由于同步机制,线程B无法到达位置3,只能在位置2等待。
3)线程A执行instance = new SingletonTwo()语句,使得instance引用指向一个对象。此时线程B还在位置2上等待。
4)线程A退出synchronized (instance),返回SingletonTwo对象,退出静态工厂方法。
5)线程B进入 synchronized (instance)块,达到位置3,此时instance已经不为null,因此线程B退出synchronized (instance),
     返回SingletonTwo对象(线程A所创建的SingletonTwo对象),退出静态工厂方法。
到此为止,线程A和B得到同一个SingletonTwo对象。
第一个if判断的作用:是为了提高程序的 效率,当SingletonTwo对象被创建以后,
再获取SingletonTwo对象时就不用去验证同步代码块的锁及后面的代码,直接返回SingletonTwo对象
第二个if判断的作用:是为了解决多线程下的安全性问题,也就是保证对象的唯一。
如果没有第二个if判断,在上面介绍的步骤5处,线程B进入synchronized (instance)块,不用去验证instance是否为null,
就会直接创建一个SingletonTwo新对象,这样整个程序运行下来就有可能创建多个实例。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值