欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

单例模式Singleton Pattern

程序员文章站 2022-07-14 07:56:47
...

单例模式:

单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例,这样的类就称为单例类。

 

单例模式的要点有三:

1) 某个类只能有一个实例。

2)它必须自行创建这个实例

3)它必须自行向整个系统提供这个实例。

 

应用场景:比如系统的日志记录,所有关联的日志都需要记录在一个文件中,此时就需用到单例模式。

 

单例模式的简单实现:

class Singleton {
	private static Singleton instance;
	
	//以保证向整个类提供这个实例
	public static Singleton getInstance() {
		if(instance == null) {
			return new Singleton();
		}
		return instance;
	}
}

 第二种实现:java在实现多线程的单例模式时,系统最好先初始化Singleton的实例。

class Singleton {
	private static Singleton instance = new Singleton();
	public static Singleton getInstance() {
		return instance;
	}
	
}

 

 

单例模式的优势和缺陷:

优点:为一个应用程序提供对象的唯一访问点,此种模式为设计及开发团队提供了共享的概念。

缺点:单例类对派生子类有很大的困难,只有在父类没有被实例化时才可以实现。

 

单例类应该注意的地方:

 

1)有些对象不能作为单例类对象,比如数据库连接对象。

2)如果实例化的对象长时间不被利用,系统会认为它是废物,自动消灭并回收它的资源,下次利用时又会重新实例化,这种情况下,应该注意其状态的丢失。

3)单例类在多线程时应该注意的问题:

 

我们来分析一下:

若在多线程中,1号线程确定了instance为null并调用getInstance方法来实例化一个新对象,但是在实例化完成之前,2号线程抢占了,也调用getInstance方法并发现instance为null,显然它又会new一个新对象。此时 我们就有两个对象了。违反了单例类得到一个实例的原则。

 

解决方法:

用synchronized加一层保护代码:

class Singleton {
	private static Singleton instance;
	
	//以保证向整个类提供这个实例
	public static Singleton getInstance() {
		if(instance == null) {
			synchronized(Singleton.class) {//1
				if(instance == null) {//2
					return new Singleton();//3
				}
			}
		}
		return instance;
	}
}

 此时我们再来分析:

当1号线程运行到//1时,获得同步锁,此时若1号线程被2号线程占用,由于instance仍未null,因此2号线程试图获得1号线程的同步锁,但此时由于1号线程仍持有该锁,2号线程被阻塞,则2号线程会被1号线程占据,1号线程再判断instance为null,因此运行到//3实例化一个新对象,并将其引用值赋给instance,1号线程退出synchronized块并返回一个instance实例,1号线程被2号线程抢占,2号线程运行//2判断instance不为null,因此不会再创建一个新对象。

 

然而,理论虽理想,但现实中确会遇到问题:并不能保证在单处理器或多处理器上能正确运行。

 

此处:详情请见:http://blog.csdn.net/kufeiyun/article/details/6166673

 

最后说一下单例模式的应用场景:

1 系统只需要一个实例对象。

2 客户调用类的单个实例只允许使用一个公共访问点。