单例模式

本文深入探讨了单例模式的三种实现方式:懒汉式、饿汉式和静态内部类方式。详细解析了每种方式的特点及适用场景,并重点讨论了懒汉式的线程安全问题及其解决方案。

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

 

一、懒汉式

1.最简单的懒汉模式(线程不安全)

package com.java.设计模式;

//懒汉式
public class Singleton1 {

	// 节省内存开销
	private static Singleton1 singleton1 = null;

	// 私有构造器,防止外部实例化对象(先不谈反射)
	private Singleton1() {
	}

	// 提供外部访问方法
	// 存在线程安全问题,当多个线程同时访问可能会创建不是同一个对象。下面会改造

	public static Singleton1 getSingleton1() {
        //简单判断,也就是这里防不住并发安全问题
		if (singleton1 == null) {
			singleton1 = new Singleton1();
		}
		return singleton1;
	}

}

2.getSingleton1方法加锁synchronized关键字

	//这里的锁对象用到的是 this锁
    //synchronized保证了线程安全性,每次只能允许一个线程进行访问
    public static synchronized Singleton1 getSingleton1() {
		if (singleton1 == null) {
			singleton1 = new Singleton1();
		}
		return singleton1;
	}

3.双重检验锁

	public static Singleton1 getSingleton1() {
		if (singleton1 == null) {
			synchronized (Singleton1.class) {
				if (singleton1 == null) {
					singleton1 = new Singleton1();
				}
			}
		}
		return singleton1;
	}

疑问:为什么要加另个if判断?

a.假设没有第一个判断,当发生并发操作时。每次调用这个方法的线程就会上锁,资源开销是相当大啊,对比判断与上锁。显然是判断语句的开销要小得多。如果已经创建了实例对象,那么就会被直接拦截。不会再进行上锁操作了。

b.假设没有第二个判断,当实例对象没有创建的时候,又同时有多个线程调用此方法。那么第一个判断肯定为true,然后会有一个线程先持有锁对象并创建对象最后释放锁资源。另外躲过利第一个if判断的线程已经进来了,不可能再跳出判断重新进来一次吧?这个时候一定会再次创建多个对象。所以第二个if判断也是很有必要的!

二、饿汉式

package com.java.设计模式;

//饿汉式
public class Singleton2 {

	//随着类的加载而加载
	private static  final Singleton2 singleton2 = new Singleton2();
	
	//私有构造器
	private Singleton2(){}
	
	//提供外部访问方法
	public Singleton2 getSingleton2(){
		return singleton2;
	}
}

饿汉式:随着类的加载而加载,在类初始化的时候就已经把类的实例化对象创建好了。所以天生线程安全,就是占内存。要是用                不到就亏了。

三、静态内部类

package com.java.设计模式;

public class Singleton3 {
	//私有构造器
	private Singleton3(){
		System.out.println("getInstance");
	}
	
	//静态内部类
	public static class SingletonInstance {
		
		private static final Singleton3 singleton3 = new Singleton3();
	}
	
	//提供外部访问方法
	public static Singleton3 getInstance() {
		return SingletonInstance.singleton3;
	}
	
}

优点:兼顾了懒汉模式的内存优化(使用时才初始化)以及饿汉模式的安全性(不会被反射入侵)。

缺点:需要两个类去做到这一点,虽然不会创建静态内部类的对象,但是其 Class 对象还是会被创建,而且是属于永久带的对象。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值