Singleton模式的一些事情

    几个项目下来,对于设计模式还是比较熟悉了,比如什么适配器模式,工厂模式,单例模式,什么原型模式等等。

    但是,对于单例模式还是有些东西可以好好说一下的。比如,写一个简单的单例模式的例子。下面的代码应该是大多数人的选择:

public class Singleton_Test_1{
	public Singleton_Test_1() {
		System.out.println("I was built");
	}
	
	private static Singleton_Test_1 singleton_Test_1 = new Singleton_Test_1();
	
	
	public static Singleton_Test_1 getInstance() {
		return singleton_Test_1;
	}
}

    乍一看,确实没什么错误。但是,如果你的类中有一个简单的方法,比如:

public static void doSomething() {
	System.out.println("We don't need singleton_Test_1");
}
	

    那么,此时会发生什么呢?

    很显然,类被创建了,但是,这个方法我们倾向于不创建单例类,而且在使用的时候可能会降低程序的反应速度。

    所以我们有了这么一个东西:

public class Singleton_Test_2 {
	
	public Singleton_Test_2() {
		System.out.println("I was built");
	}
	
	private static Singleton_Test_2 singleton_Test_2 = null;
	
	
	public static Singleton_Test_2 getInstance() {
		if (singleton_Test_2 == null) {
			singleton_Test_2 = new Singleton_Test_2();
		}
		return singleton_Test_2;
	}
}

    用一个延迟加载就能解决问题,但是,仔细看看,这个程序有没有毛病呢?其实还是有的,如果在多线程环境下,第一次调用的时候,很容易产生多个实例,这就是我们不愿意看到了。

    所以,我们加了一个同步化。就像这样:

public static synchronized Singleton_Test_2 getInstance() {
	if (singleton_Test_2 == null) {
		singleton_Test_2 = new Singleton_Test_2();
	}
	return singleton_Test_2;
}

    很简单的解决了问题,但是效率呢?不敢恭维。

    怎么办呢?现在隆重推出Holder!看代码:

public class Singleton_Test_3 {
	
	public Singleton_Test_3() {
		System.out.println("Singleton_Test_3 was built");
	}
	
	private static class singletonHolder{
		private static Singleton_Test_3 instance = new Singleton_Test_3();
	}
	
	public static Singleton_Test_3 getInstance() {
		return singletonHolder.instance;
	}
}

    在这个方法中,我们使用了内部类进行对实例的管理,这样既防止了不必要的构造,也可以加快读取速度。下面是我的测试代码,大家可以看看。

public class Singleton {
	/**
	 * @author mikecoder
	 * @see http://mikecoder.cn
	 */
	public static void main(String[] args) {
		//Singleton_Test_1.doSomething();
		//Singleton_Test_2.doSomething();
		//Singleton_Test_3.doSomething();
		
		long time1 = System.currentTimeMillis();
		for (int i = 0; i < 10000000; i++) {
			Singleton_Test_1 singleton_Test_1 = Singleton_Test_1.getInstance();
		}
		System.out.println(System.currentTimeMillis() - time1);
		
		time1 = System.currentTimeMillis();
		for (int i = 0; i < 10000000; i++) {
			Singleton_Test_2 singleton_Test_2 = Singleton_Test_2.getInstance();
		}
		System.out.println(System.currentTimeMillis() - time1);
		
		time1 = System.currentTimeMillis();
		for (int i = 0; i < 10000000; i++) {
			Singleton_Test_3 singleton_Test_3 = Singleton_Test_3.getInstance();
		}
		System.out.println(System.currentTimeMillis() - time1);
	}
}

    结果是:

    dosomething:

点击查看原图

    效率:

点击查看原图

    所以,这一次就讲到这里。

 

Leave a Reply

Your email address will not be published. Required fields are marked *