设计模式之单例模式

定义

单例模式确保一个类只有一个实例,并提供一个全局访问点。

从定义上看,这一模式的目的就是使类的一个对象成为系统中的唯一实例。

写法

单例模式有不同的实现。

饿汉法。在第一次引用该类时就创建实例,而不管实际是否需要创建。

public class Singleton {
	private static Singleton uniqueInstance = new Singleton();;

	private Singleton() {
	}

	public static Singleton getInstance() {
		return uniqueInstance;
	}
}

优点:编写简单。

缺点:相信你也看出来了,无法做到延迟加载,很多时候我们希望可以尽可能的延迟加载,从而减小系统的负担。

延迟加载

该方法利用了私有构造器和静态工厂方法。该方法保证只在需要的时候才会创建实例。

public class Singleton {
	private static Singleton uniqueInstance;

	private Singleton() {
	}

	public static Singleton getInstance() {
		if (uniqueInstance == null) {
			uniqueInstance = new Singleton();
			// 延迟加载
		}
		return uniqueInstance;
	}
}
优点:既实现了延迟加载也能在单线程下保证只有一个实例对象。

缺点:很明显的,如果两个线程同时使用getInstance()方法,很大可能会重复创建对象,也就是说它是线程不安全的。

怎么解决呢?同步!

线程安全法

public class Singleton {
	private static Singleton uniqueInstance;

	private Singleton() {
	}

	public static synchronized Singleton getInstance() {
		if (uniqueInstance == null) {
			uniqueInstance = new Singleton();
			// 延迟加载
		}
		return uniqueInstance;
	}
}
该方法利用synchronized关键字保证了同一时间只能有一个线程访问getInstance()方法,同时也实现了延迟加载。
该方法有问题么?

当然有啦!效率!

代码中,当多线程第一次执行方法时,需要同步,之后就不再需要这个同步该方法。该方法而此时每一次调用,同步都是一种浪费。

双重检查加锁

双重检查加锁(double-checked locking)减少同步

public class Singleton {
	private volatile static Singleton uniqueInstance;

	private Singleton() {
	}

	// 通过增加sysnchronized关键字,迫使每个线程进入这个方法之前,要先等其他线程离开改方法。
	public static Singleton getInstance() {
		// 检查实例,不存在则进入同步区
		if (uniqueInstance == null) {// 该部分代码只会在第一次执行
			synchronized (Singleton.class) {
				if (uniqueInstance == null) {// 进入同步后再次检查,为null才会创建实例
					uniqueInstance = new Singleton();
				}
			}
		}
		return uniqueInstance;
	}
}
双重检查加锁可以大大减少getInstance()的时间消耗。

当然还有其他好的方法,欢迎补充。

注意:

volatile 只是在线程内存和“主”内存间同步某个变量的值,
在 java 垃圾回收整理一文中,描述了jvm运行时刻内存的分配。其中有一个内存区域是jvm虚拟机栈,每一个线程运行时都有一个线程栈,线程栈保存了线程运行时候变量值信息。当线程访问某一个对象时候值的时候,首先通过对象的引用找到对应在堆内存的变量的值,然后把堆内存变量的具体值load到线程本地内存中,建立一个变量副本,之后线程就不再和对象在堆内存变量值有任何关系,而是直接修改副本变量的值,在修改完之后的某一个时刻(线程退出之前),自动把线程变量副本的值回写到对象在堆中变量。




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值