单件模式

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

package com.ez.biz;
/**
 * 单件模式,
 * @author 窗外赏雪(EZ编程网)
 */
public class Singleton {
	//利用一个私有静态变量记录类的唯一实例
	private static Singleton uniqueInstance;
	
	//私有构造方法,只有类内部才能调用构造方法
	private Singleton(){}
	//全局访问点
	public static Singleton getInstance(){
		//延迟实例化
		if(uniqueInstance == null){
			uniqueInstance = new Singleton();
		}
		return uniqueInstance;
	}
}

 

单件模式利用Java静态变量也可以做到,但是有以下缺点:

如果将对象赋给一个全局变量,那么你必须在程序一开始就创建好对象。

万一这个对象非常耗费资源,程序在这次的执行中,又没用到它,就会形成浪费了。

单件模式可以延迟实例化。

 

park停车场,当位置满的时候,就不让车辆进入。

package com.ez.biz;
/**
 * 车进入停车场时,判断车位是否有空余。
 * @author 窗外赏雪(EZ编程网)
 */
public class Park {
	//停车场一共20个车位
	private int carports = 20;
	
	//私有静态变量,记录类的唯一实例
	private static Park uniquePark;
	
	//全局访问点
	public static Park getInstance(){
		if(uniquePark==null){
			uniquePark=new Park();
		}
		return uniquePark;
	}
	
	//私有构造方法
	private Park(){}
	
	//车辆进入
	public void enter(){
		if(carports>0){
			carports--;
		}else{
			System.out.println("车位已满");
		}
	}
	
}

 

在多线程的情况下,会导致车位已经满了,但是车辆还可以进入。

 

多线程下,单件模式的处理。

把全局入口getInstance()变成同步,多线程问题就可以解决。

//全局访问点
	public static synchronized Park getInstance(){
		if(uniquePark==null){
			uniquePark=new Park();
		}
		return uniquePark;
	}

 一旦设置好uniqueInstance变量,就不再需要同步这个方法了。

 很明显,我们需要确保单件模式能在多线程的状况下正常工作,而同步getInstance()的做法将拖垮性能。

 

第一种做法:

private static Park uniqueInstance = new Park();

在静态初始化器中创建单件。这段代码保证了线程安全。

我们依赖JVM在加载这个类时,马上创建此唯一的单件实例。

JVM保证在任何线程访问uniqueInstance静态变量之前,一定先创建此实例。

 

第二种做法:

利用“双重检查加锁”,先检查实例是否已经创建,如果还没有创建,才进行同步。这样,只有第一次才会同步。

package com.ez.biz;

/**
 * 车进入停车场时,判断车位是否有空余。
 * @author 窗外赏雪(EZ编程网)
 */
public class Park {

	// 私有静态变量,记录类的唯一实例  vloatile
	private volatile static Park uniquePark;

	// 全局访问点
	public static Park getInstance() {
		if (uniquePark == null) {
			synchronized (Park.class) {
				if (uniquePark == null) {	//进入区块后,再检查一次
					uniquePark = new Park();
				}
			}
		}
		return uniquePark;
	}

}

 

 

你可能感兴趣的:(单件模式)