[java]设计模式之singleton(单例)

在日常工作中,有很多对象,我们只需要一个。比如:线程池, 缓存,注册表等。如果制造出多个实例,就会导致许多问题,如程序行为异常,资源使用过量等。这就需要对对象的构建进行控制,使其只能产生一个对象。这就是本篇要讲的设计模式——singleton(单例)。

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

那么,要如何实现单例模式,使得一个类只能产生一个对象呢?请看下面的实现:

public class Singleton {
	private static Singleton s;
	private Singleton() {
	}
	public static Singleton getInstance() {
		if (s == null) {
			s = new Singleton();
		}
		return s;
	}
}

你或许已经看懂了上面的代码。没错!我们可以通过将类的构造函数设成private访问权限,这样其他类就无法随意创建该类的对象了。然后我们应用一个静态的类对象来作为唯一的一个对象,并作为全局访问点。

clone()方法

还有一件事值得注意:类的clone()方法。例如, 如果基类实现了cloneable接口的话,子类就应该重写该方法。防止类的对象被copy,破坏单例特性。当然,在应用中应该灵活运用各种方法来防止clone()的各种情况。

多线程访问singleton方法

对于上面的实现方法,如果在多线程中被访问,可能会产生问题。

public class Singleton {
	private static Singleton s;
	private Singleton() {
	}
	// 如果多个线程同时访问, 有可能会出现多个实例。
	public static Singleton getInstance() {
		// 第一次初始化时,多个线程同时执行"if (s == null)",判断结果都为真,所以都会执行下面的操作:"s = new Singleton()",由此引发多个实例的出现。
		if (s == null) {
			s = new Singleton();
		}
		return s;
	}
}

那么该如何解决单例模式在多线程程序中的问题呢?

方案1:

将getInstance()变成同步(synchronized)方法,多线程的灾难可以轻易解决。

public class Singleton {
	private static Singleton s;
	private Singleton() {
	}

	public static <span style="color:#FF0000;">synchronized</span> Singleton getInstance() {
		if (s == null) {
			s = new Singleton();
		}
		return s;
	}
}

不推荐该方案! 因为对单例初始化只需要一次,这样做将会使得每次调用getInstance方法时都会进行同步。对运行效率是极大的累赘。

方案2:

在静态初始化时创建单例。

public class Singleton {
	// Early initialization.定义的时候就初始化。
	private static Singleton s = new Singleton();
	private Singleton() {
	}
	public static Singleton getInstance() {
		return s;
	}
}

该方法可以保证单例。但我们对程序设计时,通常保持直到使用时才创建对象的原则。

方案3:

用“双重检查加锁”,在getInstance()中减少使用同步。

public class Singleton {
	private static Singleton singleton;
	private Singleton() {
	}
	public static Singleton getInstance() {
		if (singleton == null) {
			synchronized (Singleton.class) {
				<span style="color:#FF0000;">if (singleton == null) { </span>  //必须
					singleton = new Singleton();
				}
			}
		}
		return singleton;
	}
}

这样将只有第一次创建对象时同步,既保证了线程安全,同时又保证了执行效率。

有人问为什么要在synchronized 内再一次判断if(sinlenton == null),我个人理解是这个原因:

如果两个线程都执行到了第一个if(singleton == null) 且都为true,这是总有一个线程先进入synchronized (Singleton.class)...部分代码,并阻塞另一个进入。当第一个进入后并成功建了一个实例singleton后,不再阻塞。另一个线程将进入执行synchronized (Singleton.class)...代码(因为它已经执行了第一个singleton==null 并为true)。如果里面不再进行判断,则会再一次创建一个singleton。

所以里面再一次判断了一次。

参考:

《head first 设计模式》

http://blog.csdn.net/natee/article/details/4408245#quote

时间: 2024-10-06 06:45:48

[java]设计模式之singleton(单例)的相关文章

Java设计模式:Singleton(单例)模式

概念定义 Singleton(单例)模式是指在程序运行期间, 某些类只实例化一次,创建一个全局唯一对象.因此,单例类只能有一个实例,且必须自己创建自己的这个唯一实例,并对外提供访问该实例的方式. 单例模式主要是为了避免创建多个实例造成的资源浪费,以及多个实例多次调用容易导致结果出现不一致等问题.例如,一个系统只能有一个窗口管理器或文件系统,一个程序只需要一份全局配置信息. 应用场景 资源共享的情况下,避免由于资源操作时导致的性能或损耗等.如缓存.日志对象.应用配置. 控制资源的情况下,方便资源之

Java设计模式中的单例设计

/** * 单例设计模式 * 应用场合:只需要一个对象的 * 作用:保证整个应用程序中某个实例有且只有一个 * 类型有:饿汉模式.懒汉模式 * 下面的例子是一个饿汉模式的例子 */ class SingleDemo { // 1.将构造方法私有化,不允许外部直接创建使用 private SingleDemo() {} // 2.创建类的唯一实例,使用private static修饰 private static SingleDemo instance = new SingleDemo(); //

【java设计模式】之 单例(Singleton)模式

1. 单例模式的定义 单例模式(Singleton Pattern)是一个比较简单的模式,其原始定义如下:Ensure a class has only one instance, and provide a global point of access to it. 即确保只有一个实例,而且自行实例化并向整个系统提供这个实例.单例模式的通用类如下图所示: Singleton类称为单例类,通过使用private的构造函数确保了在一个应用中只产生一个实例,并且是自行实例化的(在Singleton中

设计模式之Singleton(单例)

设计模式之Singleton(单态) 板桥里人 http://www.jdon.com 2002/05/07 定义:Singleton模式主要作用是保证在Java应用程序中,一个类Class只有一个实例存在. 在很多操作中,比如建立目录 数据库连接都需要这样的单线程操作. 还有, singleton能够被状态化; 这样,多个单态类在一起就可以作为一个状态仓库一样向外提供服务,比如,你要论坛中的帖子计数器,每次浏览一次需要计数,单态类能否保持住这个计数,并且能synchronize的安全自动加1,

[Java设计模式](一)怎样实现Singleton(单例)模式编程

单例模式是开发模式中最简单,最易于理解的一种模式.简单地说,它指的就是始终保持一个实例的意思.但是,Java的类是可以穿件多个实例的,那么,怎么实现呢? 顾名思义,单例模式就是只有一个实例.单例模式确保某一个类只有一个实例,这个类称为单例类,单例模式有3个要点: ①是某个类只能有一个实例: ②它必须自行创建这个实例: ③是它必须自行向整个系统提供这个实例.例如,一些资源管理器常常设计成单例模式. 在计算机系统中,需要管理的资源有很多,例如每台计算机可以有若干个打印机,但只能有一个打印控制器,以避

面试题集锦&amp;&amp;实现Singleton(单例)模式-JAVA版

题目:设计一个类,我们只能生产该类的一个实例.(来自<剑指Offer>) 解析:只能生产一个实例的类是实现Singleton(单例)模式的类型.由于设计模式在面向对象程序设计中起着举足轻重的作业,在面试过程中很多公司都喜欢问一些与设计模式相关的问题.在常用的模式中,Singleton是唯一一个能够用短短几十行代码完整实现的模式.因此,写一个Singleton的类型是一个很常见的面试题. 以下我们给出几种解法,供大家参考. *不好的解法一:只适用于单线程环境. 由于要求只能产生一个实例,因此我们

javascript设计模式-singleton(单例)模式

singleton(单例)模式被熟知的原因是因为它限制了类的实例化次数只能一次,单例模式,在该实例不存在的勤快下,可以通过一个方法创建一个类来实现创建类的新实例:如果实例已经存在,则会简单返回该对象的引用.单例模式不同于静态类(或对象),因为我们可以推迟它们的初始化,这通常是因为它需要一些信息,而这些信息在初始化期间可能无法获取,对于没有察觉到之前的引用代码,它们不会提供方便检索方法,这是因为它既不是对象,也不是由一个single返回的类,而是一个结构,在js中,singleton充当共享资源命

Java 设计模式 单例模式(Singleton) [ 转载 ]

Java 设计模式 单例模式(Singleton) [ 转载 ] 转载请注明出处:http://cantellow.iteye.com/blog/838473 前言 懒汉:调用时才创建对象 饿汉:类初始化时就创建对象 第一种(懒汉,线程不安全): 1 public class Singleton { 2 private static Singleton instance; 3 private Singleton (){} 4 5 public static Singleton getInstan

Singleton(单例)模式

Singleton(单例)模式用于确保某个类只有一个实例,并且为之提供一个全局访问点. Singleton模式适用情况: 当类只能有一个实例而且客户可以从一个众所周知的访问点访问它时 当这个唯一实例应该是通过子类化可扩展的,并且客户应该无需更改代码就能使用一个扩展的实例时 在任何情况下,Singleton模式都建议我们提供能够访问单例对象的公有静态方法.如果使用这个方法创建一个对象,该方法将承担确保仅创建一个实例的责任. Singleton 定义一个Instance操作,允许客户访问它的唯一实例