单例模式:确保一个类只有一个实例,并提供一个全局访问点。
要想保证一个类只有一个实例,我们不能将构造方法暴露出去,否则调用方就可能通过你提供的构造方法去实例化该类的实例,这样我们就无法保证该类只有一个实例了。因此,我们不能给类的构造方法赋予public的访问权限。
单例模式的实例化分为两种:急切实例化和延迟实例化
急切实例化:依赖JVM在加载这个类时马上创建此唯一的单件实例,通常表现为一个静态引用。如果程序总是创建并使用单件实例,或者在创建和运行时方面的负担不太繁重,我们可以采取急切实例化的方式创建单件。
public class Product {
//静态成员——将在JVM加载该类的时候就完成对象的实例化
private static Product product = new Product();
private Product(){
}
public static Product newInstance(){
//始终返回被加载时创建的静态成员实例
return product;
}
}
急切实例化单例模式UML图:
延迟实例化:只在真正需要该类的实例的时候才实例化。通常在创建和运行时负担比较重的时候选用此种方案。
public class Product {
//静态成员——之前先不去实例化对象
private static Product product;
private Product(){
}
public static Product newInstance(){
//只有在需要该类的时候调用此方法时才去完成实例化
if(null == product){
product = new Product();
}
return product;
}
}
延迟实例化单例模式UML图:
延迟实例化所面临的线程安全问题:
很多人在使用延迟实例化单例模式时都没有考虑线程安全问题。我们看下面一段代码:
/**
* 延迟实例化单例模式
*/
public class Product {
private static Product product;
private Product(){
}
public static Product newInstance() throws Throwable{
if(null == product){
Thread.sleep(5000);//这时可能会有两个线程同时进入到这里
product = new Product();//之后可能会创建两个Product类的实例
}
return product;
}
}
上段代码有时也可能只会创建一个实例,这取决哪个线程抢占到执行权,但不排除创建两个实例的可能性,有兴趣的朋友可以自己多尝试几次,或者借助调试的手段手动切换两个线程的执行顺序,就会出现创建两个实例的情景。既然如此,我们以后就不要像上面的代码这样使用延时实例化。
如何解决
延迟实例化所面临的线程安全问题:
方法一:使用synchronized,如下所示:
/**
* 延迟实例化单例模式
*/
public class Product {
private static Product product;
private Product(){
}
public static synchronized Product newInstance() throws Throwable{
if(null == product){
product = new Product();
}
return product;
}
}
上面的代码虽然能解决线程安全问题,但是每次调用newInstance方法时都会被同步,无疑会带来性能损耗,你必须知道同步一个方法可能造成程序执行效率下降100倍。如果你可以接受这样的额外损耗,你大可可以这样来用(即简单又有效),如果你可能需要频繁的调用这个同步方法,又无法接受这样的性能损失,可能就得想其他的办法啦。
方法二:使用“双重检查加锁”,如下所示:
/**
* 延迟实例化单例模式
*/
public class Product {
private volatile static Product product;//使用volatile
private Product(){
}
public static Product newInstance() throws Throwable{
if(null == product){
synchronized(Product.class){//保护起来
if(null == product){//之后再次检查
product = new Product();
}
}
}
return product;
}
}
这样做比直接使用同步方法带来的损耗要低很多。如果你不想使用synchronized,也可以使用阻塞队列,JDK也是这么推荐的。
方法三:使用急切实例化,当然之前介绍了急切实例化也有他的缺点,如果你能接受的话,这也是个简单有效的方案。
单例模式请注意多个ClassLoder
每个类加载器都定义了一个名空间,如果有两个以上的类加载器,不同的类加载器可能会加载同一个类,从整个程序来看,同一个类被加载多次,如果这样的事情发生在单件上,就会产生多个实例并存的“单件”,所以需要引起注意。
参考资料:
Head First 设计模式 (中国电力出版社)
- 大小: 3.5 KB
- 大小: 3.2 KB
分享到:
相关推荐
单例模式是一种常用的设计模式,它的核心思想是在整个应用程序中,一个类只能有一个实例存在。单例模式常用于控制资源的共享,例如数据库连接池、日志服务等。单例模式有多种实现方式,常见的包括懒汉式、饿汉式以及...
**设计模式——单例模式** 在软件工程中,设计模式是一种在特定场景下解决常见问题的标准方案,可以被复用并提升代码质量。单例模式是设计模式中的一种,它保证一个类只有一个实例,并提供一个全局访问点。这种模式...
在Qt的Qml环境中,单例模式是一种设计模式,它允许在整个应用程序中创建一个全局访问点,确保某个类只有一个实例存在。这样的设计模式在需要共享数据或者服务时非常有用,避免了多处创建相同对象导致的数据不一致或...
单例模式是软件设计模式中的一种,它保证一个类只有一个实例,并提供一个全局访问点。在C++中,实现单例模式有多种方法,我们将会深入探讨这一模式的原理、优缺点以及如何在实际编程中应用。 单例模式的核心在于...
Java设计模式之单例模式的七种写法 单例模式是一种常见的设计模式,它确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例。在计算机系统中,线程池、缓存、日志对象、对话框、打印机的驱动程序对象常...
### 设计模式总结:模板设计模式与单例模式 #### 模板设计模式 模板设计模式是一种行为型设计模式,它定义了一个算法的骨架,并允许子类为算法的某些步骤提供具体的实现。通过这种方式,算法的基本流程保持不变,...
本次我们将深入探讨两种设计模式——单例模式和装饰模式,它们在Java编程中都有着广泛的应用。 首先,让我们来理解“单例模式”。单例模式是一种创建型设计模式,其核心思想是保证一个类只有一个实例,并提供一个...
单例模式是软件设计模式中的经典模式之一,其主要目的是控制类的实例化过程,确保在应用程序的整个生命周期中,某个类只有一个实例存在。这样的设计通常适用于那些需要频繁创建和销毁,但资源消耗较大的对象,如...
单例模式(Singleton Pattern)是一种创建型设计模式,确保一个类只有一个实例,并提供一个全局访问点。这种模式常用于需要全局共享资源的场景,比如配置管理、日志记录等。 单例模式的组成 私有构造函数:防止外部...
单例模式是软件设计模式中的一种基础模式,它在Java编程中被广泛应用。单例模式的主要目的是确保一个类只有一个实例,并提供一个全局访问点。这种模式可以有效地控制资源的使用,限制实例的数量,提高性能,尤其是在...
设计模式里面的单例模式程序 package com.rrppff; public class Singleton { private static String name; public static String getName() { return name; } public static void setName(String name) { ...
单例模式是软件设计模式中的一种经典模式,它在许多场景下被广泛使用,尤其是在需要全局唯一实例的情况下。本文将深入探讨单例模式的概念、作用、实现方式以及其在实际编程中的应用。 单例模式的核心思想是确保一个...
通过研磨设计模式之单例模式的资料,你可以深入理解单例模式的原理、实现方式及其优缺点,进一步提升自己的编程技能和设计思维。学习并熟练掌握设计模式,对于成为一名优秀的Java开发者至关重要。
在软件设计模式中,单例(Singleton)是一种广泛使用的模式,它确保一个类只有一个实例,并提供全局访问点。这个模式通常用于控制共享资源的访问,比如数据库连接、线程池或者配置对象。以下是对单例模式的详细阐述...
**设计模式——单例模式** 单例模式是一种广泛应用于软件设计中的创建型设计模式,它的核心思想是确保一个类只有一个实例,并提供一个全局访问点。这样做的好处在于控制共享资源的访问,比如线程安全的数据库连接池...
Java设计模式是面向对象编程中的重要概念,它们是软件开发中经过验证的、解决常见问题的最佳实践。在这些模式中,单例模式是最为广泛使用的一种。单例模式确保一个类只有一个实例,并提供一个全局访问点,使得在整个...
Java设计模式之单例模式详解 一、单例模式概览 单例模式(Singleton Pattern)是面向对象设计模式中的一种,属于创建型模式。它确保一个类仅有一个实例,并提供一个全局访问点来访问该实例。单例模式的核心在于控制...
单例模式是软件设计模式中的一种经典模式,它在Java编程中被广泛使用,尤其是在需要控制实例化过程,或者确保某类只有一个实例时。本文将深入探讨Java中的单例模式,帮助你理解其原理和应用。 单例模式的核心思想是...