`
BestUpon
  • 浏览: 290620 次
  • 性别: Icon_minigender_1
  • 来自: 兰州
社区版块
存档分类
最新评论

单例模式(Singleton)

阅读更多

首先我们先看看一个例子,在说什么是单利模式(Singleton):

package org.bestupon.dp.singleton;
/**
* 
* @author BestUpon
* @email bestupon@foxmail.com
* @date 2010-6-13上午11:08:28
* @ask jdk中Runtime这个类似就是一个单例模式的应用:
* 
* @answer
*/
public class Test4RunTime {

public static void main(String[] args) {
Runtime runtime = Runtime.getRuntime();
runtime.freeMemory();
}
}

上面的例子可以看出在没有使用new,却获得了一个Runtime对象,这是为什么呢?让我们看看java.lang.Runtime.java的源码到底是怎么一回事:

public class Runtime { 
    private static Runtime currentRuntime = new Runtime(); 
    public static Runtime getRuntime() { 
        return currentRuntime; 
    } 
   /** Don't let anyone else instantiate this class */ 
   private Runtime() {} 
    // 以下略 
}

 以上是Runtime.java开头部分的代码,我们可以很清楚的看见,一开头就直接 new Runtime(), 一个对象,并且是静态的。在getRuntime()的时候,

直接将其返回给请求的客户端。 上面结构即采用Singleton模式设计,其结构使用 UML 描述如下所示:


Singleton的英文意义是独身,也就是只有一个人,应用在面向对象语言上,通常翻译作单例:单一个实例(Instance)。Singleton模式可以保证一个类别 只有一个实例,并只提供一个访问(visit)这个实例的方法。

1.定义:单例模式就是确保一个类中只有一个实例,并且该实例必须自动创建,并向整个系统提供该实例。

2.使用时机:当系统要求一个类只有一个实例时,就需要使用用单例模式。

 

有几个实例上面结构的方法,可以在第一次需要实例时再建立对象,也就是采用所谓的Lazy Initialization

 

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

    // .. 其它实例 
}

 上面的实例适用于单线程的程序,在多线程的程序下,以下的写法在多个线程的竞争资源下,将仍有可能产生两个以上的实例,例如下面的情况:

 

Thread1: if(instance == null) // true
Thread2: if(instance == null) // true

Thread1: instance = new Singleton(); // 产生一个实例
Thread2: instance = new Singleton(); // 又产生一个实例

Thread1: return instance; // 回传一个实例
Thread2: return instance; // 又回传一个实例

 在多线程的环境下,为了避免资源同时竞争而导致如上产生多个实例的情况,加上同步(synchronized)机制:

 

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

 不过这种简单的写法不适合用于像服务器这种服务很多线程的程序上,同步机制会造成相当的效能低落,为了顾及SingletonLazy Initialization与效能问题,因而有了Double-check Locking的模式:

 

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

 也就是只有在第一次建立实例时才会进入同步区,之后由于实例已建立,也就不用进入同步区进行锁定。JavaRuntime类别的作法简单的多, 它舍弃了Lazy Initialization,如果您要取得单例的机会不是很多,可以用这种方式:

 

public class Singleton { 
    private static Singleton instance = new Singleton(); 
    private Singleton() { 
        // .... 
    } 
    public static Singleton getInstance() { 
        return instance; 
    } 
    // 其它实例 
}

 Singleton本身的观念简单但应用 很广,因而很多时候必须对实际环境作一些考虑与调整。

3.总结:

单例模式可以分为两种:饿汉式和懒汉式两种,饿汉是在系统启动的一开始就初始化好了实例,而懒汉式是在第一次访问的时候才初始化实例。

 

package org.bestupon.dp.singleton;

/**
 * @author BestUpon
 * @email bestupon@foxmail.com
 * @date 2010-6-13上午11:34:27
 * @ask 饿汉式单利模式
 * @answer
 */
public class HungerSingleton {

	/**
	 * 一开始就初始化好了实例
	 */
	private static HungerSingleton instance = new HungerSingleton();

	private HungerSingleton() {
	}

	public static HungerSingleton getInstance() {
		return instance;
	}

}

 package org.bestupon.dp.singleton;

/**
 * 
 * @author BestUpon
 * @email bestupon@foxmail.com
 * @date 2010-6-13上午11:41:22
 * @ask 懒汉式单例模式
 * @answer
 */
public class LazySingleton {
	private static LazySingleton instance = null;

	private LazySingleton() {
	}

	public static LazySingleton getInstance() {
		if(instance == null){
			instance = new LazySingleton();
		}
		return instance;
	}
}

4.优点:

在单利模式中,客户调用类的实例时,只能调用一个公共的接口,这就为整个开发团队提供了共享的概念,

5.缺点:

单利模式在实例化后,是不允许类的继承的;在分布式系统中,当系统的单利模式类被复制运行在多个虚拟机下时,在每一个虚拟机下都会创建一个实例对象,此时如果想知道具体哪个虚拟机下运行着单例对象是很困难的,而且单例类是很难实现序列化的。

 

 

 

更新(纠正)2010-6-17:

 

由于端午节放假的缘故,各位同仁在期间提出了很多的问题,也指出了我思维的局限性,没有及时的更新于回复各位好友的,深表遗憾!


针对单例模式的很多用法,前面一直是在所单一线程的问题,本来设计多线程的问题就很少,也对双重锁定这个问题没有深入的五挖掘,导致了犯了今天这样的错误。之后参考了一些资料,针对各位朋友提出的问题与我自身存在的问题,进行改进!参考的文章是:IBMDeveloperWorks(中国)的网站上的文章双重检查锁定及单例模式http://www.ibm.com/developerworks/cn/java/j-dcl.html)。这篇文章真针对各种问题都有分析,包括可见性等问题。得出了一个结论:双重锁定失效的主要原因是:不同JVM之间的无序写入问题,多线程之间的独占、休眠(记忆复苏)所引起的不同不问题。

最终本文提出了一个建议:议不要使用“双重锁定”!一个解决单例模式的方案:

底线就是:无论以何种形式,都不应使用双重检查锁定,因为您不能保证它在任何 JVM 实现上都能顺利运行。JSR-133 是有关内存模型寻址问题的,尽管如此,新的内存模型也不会支持双重检查锁定。因此,您有两种选择:

  • 接受如清单 2 中所示的 getInstance() 方法的同步。
  • 放弃同步,而使用一个 static 字段。

选择项 2 如清单 10 中所示:

 

/**
*使用 static 字段的单例实现
**/
class Singleton
{
  private Vector v;
  private boolean inUse;
  private static Singleton instance = new Singleton();

  private Singleton()
  {
    v = new Vector();
    inUse = true;
    //...
  }

  public static Singleton getInstance()
  {
    return instance;
  }
}
 

 

再次感谢各位朋友的关注!

 

  • 大小: 10 KB
分享到:
评论
6 楼 flyboNew 2010-06-15  
renwolang521 写道

里面所说的是JDK1.3 那么在1.4 5.0和6.0中还有类似的问题吗?双重判断+同步还会存在错误码?
5 楼 linghongli 2010-06-15  
myumen 写道
搜索到个更牛的写法,既满足Lazy load,又满足只有一个实例,即使多线程环境也是一个实例。
public class Singleton {     
    
    static class SingletonHolder {     
    
        static Singleton instance = new Singleton();     
    
    }     
    
    public static Singleton getInstance() {     
    
        return SingletonHolder.instance;     
    
    }     
}

跟饿汉单例没啥区别吧
3 楼 myumen 2010-06-14  
搜索到个更牛的写法,既满足Lazy load,又满足只有一个实例,即使多线程环境也是一个实例。
public class Singleton {     
    
    static class SingletonHolder {     
    
        static Singleton instance = new Singleton();     
    
    }     
    
    public static Singleton getInstance() {     
    
        return SingletonHolder.instance;     
    
    }     
}
2 楼 Agrael 2010-06-14  
双重锁定在java里一定要保证可见性,你的例子里没保证这一点额。
1 楼 myumen 2010-06-14  
好东西,学习了

相关推荐

    单例模式 Singleton Pattern

    ### 单例模式 Singleton Pattern #### 概述 单例模式是一种常见的设计模式,属于创建型模式之一。这种模式的核心在于确保某个类只有一个实例存在,并且提供一个全局访问点来获取该实例。单例模式在Java开发中尤其...

    Java 单例模式Singleton

    简单的单例模式举例Singleton 分为恶汉式 懒汉式

    单例模式Singleton(java源码)

    单例模式的特点有三: 单例类只能有一个实例。 单例类必须自己创建自己的唯一实例。 单例类必须给所有其他对象提供这一实例。 Singleton模式包含的角色只有一个,就是Singleton。Singleton拥有一个私有构造函数,...

    单例 模式 singleton

    单例模式是一种设计模式,用于确保一个类在整个应用程序中只存在一个实例。这种模式在Java中广泛应用于需要全局访问点或资源管理的场景,比如配置管理、数据库连接池等。下面将详细阐述单例模式的实现方式、优化策略...

    单例模式Singleton

    单例模式(Singleton Pattern)是一种常用的软件设计模式,它的核心思想是确保一个类在整个应用程序中只有一个实例存在,并提供一个全局访问点来获取这个实例。这种模式在很多场景下非常有用,比如管理系统资源、...

    单例模式(singleton)

    单例模式是软件设计模式中的一种,它的核心思想是确保一个类在整个系统中只有一个实例,并提供一个全局访问点。在Java或类似编程语言中,单例模式常常被用来管理资源,比如数据库连接、线程池或者配置信息,因为这些...

    设计模式C++学习之单例模式(Singleton)

    单例模式是软件设计模式中的一种,它保证一个类只有一个实例,并提供一个全局访问点。在C++中,实现单例模式有多种方法,我们将会深入探讨这一模式的原理、优缺点以及如何在实际编程中应用。 单例模式的核心在于...

    Qt qml Singleton 单例模式

    在Qt的Qml环境中,单例模式是一种设计模式,它允许在整个应用程序中创建一个全局访问点,确保某个类只有一个实例存在。这样的设计模式在需要共享数据或者服务时非常有用,避免了多处创建相同对象导致的数据不一致或...

    单例模式(Singleton)的6种实现

    单例模式(Singleton)是设计模式中最简单也是最有争议的一个模式。它主要解决的问题是确保一个类仅有一个实例,并提供一个全局访问点。单例模式适用于那些需要全局访问的场景,比如线程池、缓存、配置对象等。单例...

    设计之模式之单例(Singleton)

    以下是对单例模式的详细阐述: 1. **单例模式的基本概念** - 单例模式的核心思想是限制类的实例化过程,只允许创建一个唯一的实例。 - 这个唯一的实例通常被静态方法管理,以保证在任何情况下都只有一个实例存在...

    ios播放单例类 singleton

    单例模式确保类只能有一个实例,并且提供一个全局访问点。在Objective-C中,通常通过以下方式实现: ```objc + (instancetype)sharedManager { static SoundManager *sharedInstance = nil; static dispatch_once...

    通过go语言实现单例模式(Singleton Pattern).rar

    在Go语言中,实现单例模式(Singleton Pattern)通常涉及确保一个类只有一个实例,并提供一个全局访问点来获取该实例。由于Go语言没有传统的类和对象概念,但具有结构体(struct)和函数,我们可以通过使用包级变量...

    Java面向对象(高级)- 单例(Singleton)设计模式

    单例模式的核心思想是限制类的实例化,确保一个类只有一个实例。实现方式通常是将类的构造器设为私有,然后通过一个静态方法(通常称为getInstance)来获取唯一的实例。这样做既可以防止外部代码直接创建对象,又...

    大话设计模式--Singleton(单例模式)

    单例模式是软件设计模式中的一种经典模式,它在许多场景下被广泛使用,尤其是在需要全局唯一实例的情况下。本文将深入探讨单例模式的概念、作用、实现方式以及其在实际编程中的应用。 单例模式的核心思想是确保一个...

    深入浅出单例Singleton模式

    单例模式是一种在软件设计中常见的设计模式,它的核心目标是确保一个类只有一个实例,并提供一个全局访问点。在Java等面向对象编程语言中,单例模式常用于控制资源的共享,如全局配置、数据库连接池、日志服务等。...

    使用C++11实现线程安全的单例模式

    这个程序会输出"Both references point to the same singleton instance.",证明了单例模式的正确实现。 总结来说,C++11通过`std::mutex`和`std::call_once`等工具,为实现线程安全的单例模式提供了强大支持。这种...

    C#单例模式详解 C#单例模式详解C#单例模式详解

    单例模式是软件设计模式中的一种,它保证一个类只有一个实例,并提供一个全局访问点。在C#中,单例模式常用于管理共享资源或控制类的实例化过程,以提高性能、节约系统资源,特别是在整个应用程序生命周期内只需要一...

    创建型模式之单例模式(Singleton Pattern)

    单例模式是软件设计模式中的一种,属于创建型模式,它的主要目的是确保一个类只有一个实例,并提供一个全局访问点。这种模式在很多场景下都非常有用,例如管理共享资源、配置对象或者缓存服务等。 单例模式的核心...

    java单例模式实例

    单例模式是软件设计模式中的一种经典模式,用于确保一个类只有一个实例,并提供一个全局访问点。在Java中,有多种实现单例模式的方法,每种都有其特点和适用场景。接下来,我们将深入探讨这些实现方式。 首先,我们...

Global site tag (gtag.js) - Google Analytics