前言
单例模式
实现步骤
方法调用·饿汉
拓展
懒汉
懒汉式的安全问题
解决方案:加锁
性能问题
解决方法
设计模式:不是技术,而是开发人员解决特定问题实现的写代码的经验
所有的设计模式核心技术,就是面向对象。
Java设计模式共23种,分为:
创建型,行为型,结构型
单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。它确保一个类只有一个实例,并提供了一个全局访问点来访问该实例。
保证一个类的对象在内存中的唯一性
public class Single {
private Single(){} //私有修饰构造方法
private Single single = new Single(); //自己创建自己的对象
}
public Single getSingle(){
return single;
想要调用此方法,则需要对象,但单例要保证对象唯一性,那我们就换一个方法:使用静态
public static Single getSingle(){
return single;
静态不能返回非静态,所以上面我们也需要加static。我们再新建一个类来测试一下
public class Single {
private Single(){} //私有修饰构造方法
private static Single single = new Single(); //自己创建自己的对象
}
public class Text {
public static void main(String[] args) {
//静态方法,获取Single类的对象
Single instance = Single.getInstance();
System.out.println("instance = " + instance);
}
}
此时不管我们instance = Single.getInstance();多少次
它的哈希值都是一样的,说明对象的唯一性,但如果new了一个新对象,哈希值就会改变
这种方式又叫“饿汉”,static静态的特点:加载速度很快,一调用静态方法,这个类就进内存了,紧接着就初始化了这个静态成员single去new对象,显得很急切地样子 (着急吃对象)
“懒汉”,又叫对象的延迟加载,与“饿汉”不同的地方,在于第二步
“饿汉”是自己创建自己的对象
“懒汉”是创建本类的成员变量,不new对象
不直接new对象的好处是,当类中有多个方法时,不管会不会用上,“饿汉”一开始就会创建对象,而“懒汉”在需要调用方法时,才会进行new对象,节省了内存
private static Single single = null;
而创建对象的操作,就置入get方法中,而if判断语句也可保证new对象的唯一性
public class Single {
private Single(){}
private static Single single = null;
public static Single getInstance(){
//判断变量s,是null就创建对象
if (single==null){
single = new Single();
}
return single;
}
}
当多线程运行时,一个线程进入if判断为null,还未进行new对象的语句,另一线程更快,也进行了判断,先一步完成new对象,此时,前一个线程要出判断语句,必然也要new一个对象,此时就产生了对象创建多次的问题。
先找到共享数据(同步代码块),然后加锁,由上面分析可知,if判断语句就是它们的共享数据
if (single==null){
single = new Single();
}
我们就用synchronized把它括住,锁就使用本类就行
public static Single getInstance(){
//判断变量s,是null就创建对象
synchronized (Single.class){
if (single==null){
single = new Single();
}
}
return single;
}
把锁加上后,即使前一个线程已进入判断语句,CPU找了另一个线程想进来,但锁在前一个线程的身上,只要这个线程未出去,锁就不会还回来,其他线程也就只能在共享数据外等待
当然,加锁会让效率变低,但可以保证安全性
程序慢点没关系,但一定要安全!!!
第一个线程获取锁,创建对象,返回对象.第二个线程调用方法的时候,变量s已经有对象了,根本就不需要再进同步,也不需要判断null,直接return才是最高效的
使用双重if判断,解决上文效率问题。
多加一个if判断,只要有了一个对象,后来的线程就不再进入同步,直接跳过锁返回,即使两个线程都同时通过了第一个if判断,在锁内部仍有一个if判断,强制把多个锁前后分开,先进锁的创建对象,进锁的其他线程在第二个判断时不为null,直接return。
public static Single getInstance(){
if (single==null) { //第一重判断
//判断变量s,是null就创建对象
synchronized (Single.class) {
if (single == null) { //第二重判断
single = new Single();
}
}
}
return single;
}
今天的Java文章分享就到此结束了, 喜欢的小伙伴记得一键三连,点赞收藏评论,如果想了解更多内容,可以用未来百万富豪的手指,点点小小的关注!你们的支持就是我最大的动力!