单例模式

单例模式

单例模式是一种常见的设计模式,它提供了一种在多线程情况下保证实例的唯一性方案。单例模式有以下几个特点:

1)单例类只能有一个实例;
2)单例类必须创建自己的唯一实例;
3)单例类必须给其他所有对象提供这一实例。

单例模式确保某个类只能有一个且必须创建自己的唯一实例,并把这个唯一实例提供给整个系统。比如在计算机系统中,线程池、打印机、对话框等常被设计成单例,计算机上有很多的通信端口,我们必须保证一个端口只能被一个请求同时调用,否则会出现混乱。

1、饿汉式

// 加final不允许被继承。
public final class SingletonHungry {
	
	// 实例变量。
	private byte[] data = new byte[1024];
	
	// 在定义实例对象时直接初始化。
	private static SingletonHungry instance = new SingletonHungry();
	
	// 私有构造函数,不允许外部调用。
	private SingletonHungry() {
		
	}
	
	public static SingletonHungry getInstance() {
		return instance;
	}
}

饿汉式的关键在于instance作为类变量并直接得到了初始化。在类初始化的过程中会被收集进()方法中,该方法能够保证百分百保证同步,这样只要一主动使用singleton类,就会直接完成创建,其中的实例变量也会得到初始化,而不能被再次实例化。

由于getInstance方法无法进行懒加载,如果一个类中的成员属性比较少,占用的内存资源较少,饿汉式是适用的。但当成员较多时,就变得不适用了。

2、懒汉式

public final class SingletonLazy {

	// 实例变量。
	private byte[] data = new byte[1024];
	
	// 定义实例,不直接初始化。
	private static SingletonLazy instance = null;
	
	private SingletonLazy(){
		
	}
	
	public static SingletonLazy getInstance() {
		if(instance == null) instance = new SingletonLazy();
		return instance;
	}
}

懒汉式就是在使用类的实例的时候再去创建。但由于在SingletonLazy.class被初始化时instance没有被实例化,而是在getInstance方法中先判断它是否被实例化而再去创建实例,这会导致在多线程的情况下,如果多个线程都看到了instance==null,那么instance很可能会被实例化多此,而不能保证单例的唯一性。

3、懒汉式+同步方法

public final class SingletonLazySyn {

	// 实例变量。
	private byte[] data = new byte[1024];
	
	private static SingletonLazySyn instance = null;
	
	private SingletonLazySyn() {
		
	}
	
	// 加synchronized同步控制,每次只能有一个线程执行。
	public static synchronized SingletonLazySyn getInstance() {
		if(null == instance) instance = new SingletonLazySyn();
		return instance;
	}
}

懒汉式+同步方法既满足懒加载又绝对保证instance实例的唯一性,但是阻塞的方式会导致性能低下。

4、枚举方式

使用枚举方式实现单例模式是《Effective Java》作者力推的方式。

枚举类型不允许被继承,线程安全且保证实例唯一性。对Singleton主动使用,INSTANCE会立即实例化。

// enum本身是final的,不允许被继承。
public enum SingletonEnum {

	INSTANCE;
	
	// 实例变量。
	private byte[] data = new byte[1024];
	
	SingletonEnum() {
		
	}
	
	public static void method() {
		// 调用此方法,则是主动使用SingletonEnum,INSTANCE将会被实例化。
	}
	
	public static SingletonEnum getInstance() {
		return INSTANCE;
	}
}

增加懒加载特性:

public class SingletonEnumLazy {

	// 实例变量。
	private byte[] data = new byte[1024];
	
	private SingletonEnumLazy() {
		
	}
	
	public static SingletonEnumLazy getInstance() {
		return EnumHolder.INSTANCE.getInstance();
	}
	
	// 使用枚举。
	private enum EnumHolder{
		INSTANCE;
		private SingletonEnumLazy instance;
		
		EnumHolder() {
			this.instance = new SingletonEnumLazy();
		}
		
		private SingletonEnumLazy getInstance() {
			return instance;
		}
	}
}

另外还有Double-Check、volatile+Double-Check、Holder等实现方式,后续补充。

参考书籍《Java高并发编程详解》。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值