单例模式的几种写法

测试类

/**
 * @author mnmlist@163.com
 * @date 2017/05/21
 * @time 12:04
 */
public class SingletonDemo {
	public static void main(String[] args) {
		// test Singleton1
		System.out.println(Singleton1.getInstance());

		System.out.println(Singleton2.getInstance());

		System.out.println(Singleton3.getInstance());

		System.out.println(Singleton4.getInstance());

		System.out.println(Singleton5.INSTANCE);
	}
}

单例模式

1. 饿汉模式

/**
 * 饿汉模式
 * 优点:书写简单,JVM本身保证一个类在一个ClassLoader中只会被初始化一次
 * 缺点:a.加载就初始化;b.这种创建方法并不灵活,例如实例是依赖参数或者配置文件的
 */
class Singleton1 {
 private static final Singleton1 singleton1 = new Singleton1();

 private Singleton1() {}

 public static Singleton1 getInstance() {
   return singleton1;
 }
}

2. 懒汉模式,对整个方法加锁

/**
 * 优点:简单
 * 缺点:效率低,对整个方法进行加锁,而真实的情况是只有singleton实例为null的时候才需要对方法加锁
 */
class Singleton2 {
	private static volatile Singleton2 singleton2;

	private Singleton2() {}

	//直接对整个方法加锁,但多数情况下是null != singleton2的,也就是执行到null == singleton2判断就return的
	//所以对整个方法进行加锁效率太低
	public static synchronized Singleton2 getInstance() {
		if (null == singleton2) {
			singleton2 = new Singleton2();
		}
		return singleton2;
	}
}

3. 懒汉模式,对关键语句加锁

/**
 * 优点:看起来挺有技术含量
 * 缺点:其实太复杂,不够简洁
 */
class Singleton3 {
	private volatile static Singleton3 singleton3;  //volatile 禁止singleton3 = new Singleton3();指令重排

	private Singleton3() {}

	public static Singleton3 getInstance() {

		//先判断singleton3是否为null,对象已经存在的话就不用再同步了,提升效率
		if (null == singleton3) {
			synchronized (Singleton3.class) {

				//加锁的过程中可能singleton3已经被赋值,所以还需要再判断下,防止出错
				if (null == singleton3) {

					/**
					 * 该操作并不是一个原子操作,它其实包括3个步骤,
					 *  1. 给 singleton 分配内存
					 *	2. 调用 Singleton 的构造函数来初始化成员变量,形成实例
					 *	3. 将singleton对象指向分配的内存空间
					 * 在 JVM 的即时编译器中存在指令重排序的优化。也就是说上面的第二步和
					 * 第三步的顺序是不能保证的,最终的执行顺序可能是 1-2-3 也可能是 1-3-2,
					 * 所以把singleton声明成 volatile,防止指令因指令重排导致问题
					 */
					singleton3 = new Singleton3();
				}
			}
		}
		return singleton3;
	}
}

4. 静态内部类实现懒汉模式

/**
 * 静态内部类实现,简单且不需要额外的同步
 */
class Singleton4 {
	public Singleton4() {
	}

	/**
	 * getInstance()方法被调用的时候才会初始化实例
	 */
	public static Singleton4 getInstance() {
		return SingletonHolder.INSTANCE;
	}

	private static class SingletonHolder {
		public static Singleton4 INSTANCE = new Singleton4();
	}
}

5. 枚举形式的单例,简单安全

/**
 * 保证单例且线程安全
 */
enum Singleton5 {
	INSTANCE;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值