Head First(五)--单例模式

单例模式可以确保只有一个实例会被创建。单例模式给了我们一个全局的访问点,和全局变量一样方便,又没有全局变量的缺点。全局变量的缺点:如果将对象赋值给一个全局变量,那么你必须在程序一开始就创建好对象。万一这个对象非常耗费资源,而程序在这次的执行过程中又一直没用到它,不就形成浪费了吗?单例模式,我们可以在需要时才创建对象。

public class Singleton {

	private static Singleton uniqueInstance;

	private Singleton() {
	}

	public static Singleton getInstance() {
		if (uniqueInstance == null) {
			return new Singleton();
		}
		return uniqueInstance;
	}
}
利用一个静态变量来记录Singleton类的唯一实例。
把构造器声明为私有的,只有Singleton类内才可以调用构造器。
用getInstance()方法实例化对象,并返回这个实例。
Singleton是一个正常的类,具有一些其他用途的实例变量和方法。
作用:

如果有一个注册表设置(registry setting)的对象,你不希望这样的对象有多个拷贝把?那会把设置搞得一团乱。利用单例对象,可以确保程序中使用的全局资源只有一份。
独身是有些好处的。我常常被用来管理共享的资源,例如数据库连接或者线程池。

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

上面这段代码,利用延迟实例化的方式创建单例,这种做法对资源敏感的对象特别重要。

多线程的情况下,有可能产生多个实例,解决方案如下:

只要把getInstance()变成同步(synchronized)方法,多线程灾难几乎就可以轻易地解决了。

public class Singleton {

	private static Singleton uniqueInstance;

	private Singleton() {
	}

	public static synchronized Singleton getInstance() {
		if (uniqueInstance == null) {
			return new Singleton();
		}
		return uniqueInstance;
	}
}
通过增加synchronized关键字到getInstance()方法中,我们迫使每个线程在进入这个方法之前,要先等候别的线程离开该方法。也就是说,不会有两个线程可以同时进入这个方法。

同步会降低性能。并且,单例模式,其实只要第一次创建对象的时候需要同步,以后再访问的时候,都是拿第一次创建的那个对象。如何改善?

1.如果getInstance()的性能对应用程序不是很关键,就什么都别做
如果你的应用程序可以接受getInstance()造成的额外负担,就忘了这件事把。同步getInstance()既简单又有效。但是你必须知道,同步一个方法可能造成程序执行效率下降100倍。因此,如果将getInstance()的程序使用在频繁运行的地方,你可能就得重新考虑了。
2.使用“急切”创建实例,而不用延迟实例化的做法
如果应用程序总是创建并使用单例实例,或者在创建和运行时方面的负担不太繁重,你可能想要急切(eagerly)创建此单例。

public class Singleton {

	private static Singleton uniqueInstance = new Singleton();

	private Singleton() {
	}

	public static synchronized Singleton getInstance() {
		return uniqueInstance;
	}
}
上面代码,在静态初始化器(static initialize)中创建单例。这段代码保证了线程安全。

利用这个做法,我们依赖JVM在加载这个类时马上创建唯一的单例实例。JVM保证在任何线程访问uniqueInstance静态变量之前,一定先创建此实例。

扫描二维码关注公众号,回复: 57158 查看本文章

3.用“双重检查加锁”,在getInstance()中减少使用同步
利用双重检查加锁(double-checked locking),首先检查实例是否已经创建,如果尚未创建,“才”进行同步。这样一来,只有第一次会同步,这整是我们想要的。

public class Singleton {

	private volatile static Singleton uniqueInstance;

	private Singleton() {
	}

	public static Singleton getInstance() {
		if (uniqueInstance == null) {
			synchronized (Singleton.class) {
				uniqueInstance = new Singleton();
			}
		}
		return uniqueInstance;
	}
}

Java单例模式——并非看起来那么简单

看上面链接,足够了。

猜你喜欢

转载自blog.csdn.net/csdn_kenneth/article/details/79235328