单例模式
概述:
使用场景:在当前系统中,某个类型的对象,最多只能有一个,就需要使用单例设计模式
单例模式的设计原则:
- 构造方法私有化,禁止外界随意创建实例
- 在类中创建好该类对象
- 在类中,给外界提供获取该对象的公有方式
单例模式主要分为两种方式:饿汉式、和懒汉式
单例模式中的饿汉式
饿汉式原理:
- 首先将类的构造函数私有化,禁止外部创建类的实例。
- 然后在类中创建一个静态的本类类型私有的静态成员
- 提供一个公开的供外部访问获取对象的静态方法
相关代码:
class Singleton{
//直接在类加载时就创建好对象
private static Singleton singleton=new Singleton();
//构造函数私有化,禁止外部直接创建实例
private Singleton() {}
//对外提供公有方法供外部访问获取对象
public static Singleton getInstance() {
return singleton;
}
}
测试代码:
Singleton sl1 = Singleton.getInstance();
Singleton sl2 = Singleton.getInstance();
System.out.println(sl1==sl2);//结果为true
饿汉式存在的弊端:
在还没有使用对象时,就会在堆内存中开辟一块空间,对空间和资源有一点点浪费
饿汉式的另一种形式
原理:
- 同样是首先将类的构造函数私有化,禁止外部创建类的实例。
- 然后直接创建对象,把访问权限设置为公有化,同时,为了防止被外界修改,在前面加上final关键字修饰,这样一来,外界只能访问该变量,而不能去修改该变量。
相关代码:
class Singleton2{
//构造方法私有化,禁止外界直接创建实例
private Singleton2() {}
/*直接创建对象,把权限设为公开,然后状态设为静态
1. 为了防止外界修改,加一个final关键字修饰
*/
public static final Singleton2 sl=new Singleton2();
}
单例模式中的懒汉式
懒汉式原理
- 首先构造方法私有化,限制外界创建实例
- 创建对象(此时为NULL)注意为私有且静态
- 为外界提供一个公开的获取对象的访问方式(注意这里的实现细节,如代码中所示)
相关代码:
class SingletonLazy{
//此时的实例为NULL
private static SingletonLazy sllz;
//构造方法私有化,禁止外界创建实例
private SingletonLazy() {
}
public static SingletonLazy getInstance() {
/*
* 外侧加if的原因:
* 我们获取线程锁对象效率非常低,经常需要等待
* 上一个同步锁的释放,然后再进入同步代码块里进行
* 判断,这样次数一多,会严重影响系统效率
* 所以外侧if可以大大提高系统效率
*
* 注意事项:内外层的if语句缺一不可,内层保障线程安全,外层保障系统效率
* 假设,去掉了内层的if,就又会产生A、B线程由于CPU的切换而绕过if判断,进而去重复创建对象
* */
if (sllz==null) {
/*
* 在多线程的情况下,内层的if很容易产生线程安全问题
* 假设A线程在判断完毕实例不存在后,此时cpu转走
* cpu去执行B线程,然后创建对象之后,cpu切回来继续执行线程A
* 此时就会创建出新的实例,这就违反了单一实例原则
* */
synchronized (SingletonLazy.class) {
//判断实例是否已经被创建,如果有没有就创建,有就不会再创建
if (sllz == null) {
sllz = new SingletonLazy();
}
}
}
return sllz;
}
}
总结:通过上面我们不难发现懒汉式对于而言要繁琐的多,在实际开发中,
我们用饿汉式也是比较多些。
希望这篇文章能对你有所帮助,觉得还可以的可以点个赞支持一下~