问到吐的单例模式

单例模式

核心作用,保证一个类只有一个实例,并且提供一个访问该实例的全局访问点

单例模式的优点

由于单例模式值生成一个实例,减少了系统开销,当一个对象的产生需要比较多大资源的时候,如读取配置文件,产生其他依赖对象,则可以通过在应用启动时直接产生一个对象,然后永久驻留内存.单例模式可以在系统设置全局的访问点,优化共享资源访问.

常见5中实现:

  1. 饿汉式(线程安全,效率高,但是,不能延时加载)
  2. 懒汉式(线程安全,效率不高,但是可以延时加载)
  3. 双重检测锁(由于JVM底层内部模型原因,偶尔会出问题,不建议使用)
  4. 静态内部类(线程安全,调用效率高,但是,可以延时加载)
  5. 枚举单例(线程安全,调用效率高,不能延时加载)
饿汉式
public class SingleDemo {
	
	//类加载直接创建实例,类加载时是线程安全的,所以getSingle不需要同步
	private static SingleDemo single = new SingleDemo();
	
	//但是模式私有构造器
	private SingleDemo() {}
	
	//保证了对象的单例
	public static SingleDemo getSingle() {
		return single;
	}
}
懒汉式
public class SingleDemo {
	
	//先不创建对象
	private static SingleDemo single;
	
	//但是模式私有构造器
	private SingleDemo() {}
	
	//只有在调用方法,确保single是null没有创建在new对象,为了线程安全有 synchronized 所以效率不高,但是可以延时加载
	public static synchronized SingleDemo getSingle() {
		if(single == null) {
			single = new SingleDemo();
		}
		return single;
	}
}
双重检测锁

public static Singleton getInstance()
{
  if (instance == null)
  {
    synchronized(Singleton.class) {  //1
      if (instance == null)          //2
        instance = new Singleton();  //3
    }
  }
  return instance;
}

线程 1 进入 getInstance() 方法。

由于 instance 为 null,线程 1 在 //1 处进入 synchronized 块。

线程 1 被线程 2 预占。

线程 2 进入 getInstance() 方法。

由于 instance 仍旧为 null,线程 2 试图获取 //1 处的锁。然而,由于线程 1 持有该锁,线程 2 在 //1 处阻塞。

线程 2 被线程 1 预占。

线程 1 执行,由于在 //2 处实例仍旧为 null,线程 1 还创建一个 Singleton 对象并将其引用赋值给 instance。

线程 1 退出 synchronized 块并从 getInstance() 方法返回实例。

线程 1 被线程 2 预占。

线程 2 获取 //1 处的锁并检查 instance 是否为 null。

由于 instance 是非 null 的,并没有创建第二个 Singleton 对象,由线程 1 创建的对象被返回。
双重检查锁定背后的理论是完美的。不幸地是,现实完全不同。双重检查锁定的问题是:并不能保证它会在单处理器或多处理器计算机上顺利运行。

双重检查锁定失败的问题并不归咎于 JVM 中的实现 bug,而是归咎于 Java 平台内存模型。内存模型允许所谓的“无序写入”,这也是这些习语失败的一个主要原因。但在JDK1.5后可以通过 volatile 修饰来解决但这也是不推荐的

详细解释

静态内部类

当初始化类的时候,并不会立即初始化它的静态内部类,只有用的时候才初始化,兼备并发高效延时加载,推荐使用

public class SingleDemo {
	
	//单实例作为静态内部类的成员变量
	private static class SingleDemoInstance{
		private static final SingleDemo single = new SingleDemo();
	}

	//只有在调用方法,确保single是null没有创建在new对象,为了线程安全有 synchronized 所以效率不高,但是可以延时加载
	public static SingleDemo getSingle() {
		return SingleDemoInstance.single;
	}

	//但是模式私有构造器
	private SingleDemo() {}
	
}
枚举单例模式

枚举对象天然是单例的,每个枚举元素都是一个实例,枚举可以避免反射,反序列化漏洞创建对象(没有延时加载)

public enum SingleEnum {

	//枚举元素本身就是一个实例,天然的单例 
	INSTANCE;
	
	//像用其他类一种添加功能处理,
	public void operation() {
		
	}
}

执行效率

从优到次

饿汉式<静态内部类<枚举<双重检测锁<懒汉式

  咸鱼IT技术交流群:89248062,在这里有一群和你一样有爱、有追求、会生活的朋友! 大家在一起互相支持,共同陪伴,让自己每天都活在丰盛和喜乐中!同时还有庞大的小伙伴团体,在你遇到困扰时给予你及时的帮助,让你从自己的坑洞中快速爬出来,元气满满地重新投入到生活中!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值