码迷,mamicode.com
首页 > 其他好文 > 详细

单例模式

时间:2015-09-02 17:16:15      阅读:131      评论:0      收藏:0      [点我收藏+]

标签:

定义

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

代码实现

有如下几种实现单例模式的方法:

急切实例化

使用“急切”创建实例,而不用延迟实例化的做法。在静态初始化器中创建单例,保证了线程安全。

public class Singleton { // √
	private static Singleton instance = new Singleton();
	private Singleton() {}
	public static Singleton getInstance() {
		return instance;
	}
}
同步getInstance()方法
class Singleton2 {
	private static Singleton2 instance;
	private Singleton2() {}
	public static synchronized Singleton2 getInstance() {
		if (instance == null) {
			instance = new Singleton2();
		}
		return instance;
	}
}

同步getInstance()的做法将拖垮性能(同步一个方法可能造成程序执行效率下降100倍),一般不采用这种做法。

双重检查加锁
class Singleton3 { // √ , 比 Singleton2  好
	private volatile static Singleton3 instance;
	private Singleton3() { }
	public static Singleton3 getInstance() {
		if (instance == null) {
			synchronized(Singleton3.class) {
				if (instance == null) {
					instance = new Singleton3();
				}
			}
		}
		return instance;
	}
}

volatile关键词确保:当instance变量被初始化成Singleton3实例时,多个线程正确地处理instance变量。

volatile与synchronized

Java有个思想叫“主”内存区域,这里存放了变量目前的“准确值”。

(1) 一个变量经 volatile修饰后在所有线程中必须是同步的;任何线程中改变了它的值,所有其他线程立即获取到了相同的值;

(2) 看下面的一段代码:

private int i3;  
synchronized int geti3() {return i3;}

首先,synchronized获得并释放监视器——如果两个线程使用了同一个对象锁,监视器能强制保证代码块同时只被一个线程所执行。
但是,synchronized也同步内存:事实上,synchronized在“主”内存区域同步整个线程的内存。因此,执行geti3()方法做 了如下几步:
1>. 线程请求获得监视this对象的对象锁(假设未被锁,否则线程等待直到锁释放)
2>. 线程内存的数据被消除,从“主”内存区域中读入(Java虚拟机能优化此步。。。[后面的不知道怎么表达,汗])
3>. 代码块被执行
4>. 对于变量的任何改变现在可以安全地写到“主”内存区域中(不过geti3()方法不会改变变量值)
5>. 线程释放监视this对象的对象锁

 

单例模式

标签:

原文地址:http://www.cnblogs.com/xwz0528/p/4779007.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!