单例模式-

单例模式确保一个类只有一个实例,常用于资源管理如数据库连接。Java中实现单例模式包括懒加载、线程安全和防止反射破坏。双检锁写法结合了懒加载和线程安全,但需使用`volatile`避免指令重排。静态内部类写法利用类加载机制实现懒加载,线程安全且避免反射破坏。
摘要由CSDN通过智能技术生成

什么是单例模式,为什么需要单例模式?

单例模式,就是在运行时域,一个类只有一个实例对象。
有时候一个类的创建和销毁对资源的消耗特别大,并且如果这些类是完全可以复用的话,那么将会造成不必要的性能浪费
比如数据库连接的操作,创建连接对象是一个消耗资源的操作,并且这个操作完全是可以复用的,那么就可以将这个对象设计成一个单例的,这样我就可以创建一次,并且重复使用这个对象就可以了

java中如何实现单例模式

写单例模式主要考虑三点
1、是不是懒加载
2、线程是不是安全
3、能不能通过反射破坏

双检锁写法
public class Singletone{
	private Singleton(){}  //构造器私有,这样其它类就不能直接new了
	private static Singleton insetance = nell;    //初始化对象为null
	public static Single getInstance(){
		if(instance == null){
			instance =new Singleton();
		}
		return instance;
	}
}


这种实例对象实在第一次被调用的时候下真正构建的,而不是程序启动的时候就构建好了等着你调用的,这种之后构建的方式就叫做懒加载 

有的对象的构建开销是比较大的,加入这个对象在启动的时候就构建万一没被调用就浪费了,这就能体现出懒加载的优势

但是此时的线程是不安全的,可以在第一次创建对象的时候加锁,以后会跳过这一步

public class Singletone{
	private Singleton(){}  //构造器私有,这样其它类就不能直接new了
	private static Singleton singleton = nell;    //初始化对象为null
	public static Single getInstance(){   // 1
		if(singleton == null){   //  2
			synchronized(Singletone.class){  //3
				singleton =new Singleton();   //4
			}
		}
		return instance;
	}
}
如果有多个线程同是进入  if 语句中,那么就会创建多个线程,这也是不好的,所以我们在加入一个判空,构成**双检锁**就可以解决


public class Singletone{
	private Singleton(){}  //构造器私有,这样其它类就不能直接new了
	private static Singleton singleton = nell;    //初始化对象为null
	public static Single getInstance(){   
		if(singleton == null){   
			synchronized(Singletone.class){ 
				if(singleton == null){
					singleton =new Singleton(); 
				}  
			}
		}
		return instance;
	}
}

此时不满足java多线程的happens-before 原则(定义了多线程可见性问题)
因为在singleton =new Singleton(); 在指令层面不是一个原子的操作,她分为了三步1、分配内存 2、初始化对象 3、对象指向内存地址,在真正执行是,jvm虚拟机微课效率可能会对指令进行重排,同样会产生线程不安全的问题,此时加上一个volatile 关键字就能阻止作用在singleton 对象上的指令重排问题下。面写法满足了懒加载,阻止了指令重排,线程安全,叫双检锁写法 缺点是写起来比较复杂

public class Singletone{
	private Singleton(){}  //构造器私有,这样其它类就不能直接new了
	private volatile static Singleton singleton = nell;    //初始化对象为null
	public static Single getInstance(){   
		if(singleton == null){   
			synchronized(Singletone.class){ 
				if(singleton == null){
					singleton =new Singleton(); 
				}  
			}
		}
		return instance;
	}
}



静态内部类写法
public class Singleton{
	private static class SingletonHolder{
		private static final Single INSTANCE = new Singleton();
	}
	private Single(){}
	public static final Singleton getInstance(){
		return SingletonHolder.INSTANCE ;
	}
}

静态内部类在程序启动时不会加载,只有在第一次被调用时候才会加载(利用jdk加载机制的特性来实现懒加载)
以上的两种方式会被反射破坏(人为破坏)可以考虑枚举类,同是枚举类是线程安全的,但是不能满足懒加载,所以现在没有方法满足三种要求

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值