1、单例模式定义
在整个应用中,同一时刻,有且只能有一种状态的类可以考虑写成单例模式;
2、单例模式的好处
节约内存空间,减少无谓的GC消耗;
3、单例模式示例代码
3.1 标准的单例模式- 这种是在不考虑并发的情况下的代码,所以不是很严谨;
public class Singleton { //一个静态的实例 private static Singleton singleton; //私有化构造函数 private Singleton(){} //给出一个公共的静态方法返回一个单一实例 public static Singleton getInstance(){ if (singleton == null) { singleton = new Singleton(); } return singleton; } }
3.2 为防止并发的情况实例化多个破坏单例模式,以下代码加了同步锁来避免这种情况;
public class SynchronizedSingleton { //一个静态的实例 private static SynchronizedSingleton synchronizedSingleton; //私有化构造函数 private SynchronizedSingleton(){} //给出一个公共的静态方法返回一个单一实例 public synchronized static SynchronizedSingleton getInstance(){ if (synchronizedSingleton == null) { synchronizedSingleton = new SynchronizedSingleton(); } return synchronizedSingleton; } }
3.3 上面3.2的这种在方法上加同步锁的做法可以避免产生多个实例的问题,在一个线程访问这个方法时,其它所有的线程都要处于挂起等待状态,但是在实例创建以后,获取实例的方法就没必要再进行同步控制了;所以,可以考虑把同步锁往下放,放到产生实例的语句块上,来形成一个同步语句块锁;
public class SynchronizedSingleton { //一个静态的实例 private static SynchronizedSingleton synchronizedSingleton; //私有化构造函数 private SynchronizedSingleton(){} //给出一个公共的静态方法返回一个单一实例 public static SynchronizedSingleton getInstance(){ if (synchronizedSingleton == null) { //(1) synchronized (SynchronizedSingleton.class) { //同步语句块 if (synchronizedSingleton == null) { //这里进行了又一次判断,是为了防止线程A创建完实例释放同步锁,线程B已经过了语句“(1)”的判断进入同步块继续创建实例; synchronizedSingleton = new SynchronizedSingleton(); } } } return synchronizedSingleton; } }
假设我们去掉同步块中的是否为null的判断,有这样一种情况,假设A线程和B线程都在同步块外面判断了synchronizedSingleton为null,结果A线程首先获得了线程锁,进入了同步块,然后A线程会创造一个实例,此时synchronizedSingleton已经被赋予了实例,A线程退出同步块,直接返回了第一个创造的实例,此时B线程获得线程锁,也进入同步块,此时A线程其实已经创造好了实例,B线程正常情况应该直接返回的,但是因为同步块里没有判断是否为null,直接就是一条创建实例的语句,所以B线程也会创造一个实例返回,此时就造成创造了多个实例的情况。
[以上内容摘自博客园:http://www.cnblogs.com/zuoxiaolong/p/pattern2.html ]