单例模式的几种实现方式
Posted *^O^*—*^O^*
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了单例模式的几种实现方式相关的知识,希望对你有一定的参考价值。
单例模式介绍
属于设计模式的一种,不是Java独有,一种类型,为其他调用方提供本类的实例对象,始终都是同一个对象
使用场景
使用jdbc操作数据库的时候,此时数据库连接可以通过数据库连接池来获取,为了防止出现多个对象操作数据库,产生并发执行事务,就会产生一系列的问题,这里最好的就是让操作直接串行化,就可以避免这所有的问题了,那怎么串行化,只有一个对象来进行操作,肯定也就只能依次操作了,
实现方式
设计思想就是两个:
1)私有的构造方法(外部就不能new了,否则就不是同一个对象了)
2)内部构造同一个对象,提供开发的方法给外部使用
private 当前类(){}
public static 当前类型 getInstance(){
return 内部new的同一个对象
}
饿汉式(线程安全)
class Singleton {
private static Singleton instance = new Singleton();
private Singleton() {}
public static Singleton getInstance() {
return instance;
}
}
类加载的时候就初始化了,就存在一点缺点
1.还没有使用,就浪费了内存空间;
2.new对象(没有执行类加载,会先执行,再执行成员变量+实例代码块+构造方法),可能抛出异常,下一次使用就使用不了了。
懒汉式(线程不安全)
class Singleton {
private static Singleton instance = null;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
instance = new Singleton();可以分解成三行字节码指令
是对共享变量的多行指令操作,就不具有线程安全,当初始化时,多个对象同时判定为null,就会都进入创建,这里就是线程不安全的。
静态同步方法+懒汉式(线程安全)
class Singleton {
private static Singleton instance = null;
private Singleton() {}
public synchronized static Singleton getInstance() {
if (instance == null) { //1
instance = new Singleton(); //2
}
return instance; //3
}
}
效率比较差,因为这里把下面的三个条都加锁了,但是这里的1和3是具有原子性的,可以只需要保证可见性,就是线程安全的,但是因为这里的创建只有一次,使用是多次的,所以这里效率是不高的。
双重校验锁(线程安全)
class Singleton {
private static volatile Singleton instance = null;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
这里就将上述所说的加上了volatile关键字,保证了可见性,所以执行创建完成之后的代码,就不需要加锁的,
这里第二个 if 存在的原因是:申请锁失败的线程,再重新获取锁,执行代码时,如果没有再次判断,就会创建一个新的对象,也就不满足单例的概念了
1.初始化完成之后,不需要加锁,使用volatile修饰变量,保证可见性,能满足线程安全(代码本身就是原子性),这样就可以并发并行的执行,提高了执行效率
2.没有初始化完成时,创建对象需要加锁来保证线程安全
3.竞争锁失败的线程,还会执行同步代码,需要再次判断,保证只初始化一次
4,引用使用了volatile关键字,还有建立内存屏障,禁止指令重排序的功能(new 分解的三条指令)
以上是关于单例模式的几种实现方式的主要内容,如果未能解决你的问题,请参考以下文章