- 浏览: 284301 次
- 性别:
- 来自: 兰州
文章分类
- 全部博客 (116)
- 给网友答疑 (1)
- J2EE (16)
- DesignPattern (14)
- OtherArchive (5)
- lucene and compass (1)
- JasperReport (2)
- FusionCharts (2)
- Classical algorithm (2)
- JS (5)
- ZK Ajax (1)
- ubuntu-linux (4)
- Weka (0)
- IDE Config (6)
- JAVA 底层 (3)
- C\C++ (4)
- Android (15)
- 项目展示 (1)
- 娱乐生活 (16)
- 电驴资源 (1)
- 网络转载 (1)
- 程序员 毛病 (1)
- Android,开发日志 (2)
- java (1)
- openGL es (2)
- MAC (1)
最新评论
-
洋葱pp奥特曼:
求大神再发一次资源,万分感激!!小弟邮箱:173992660@ ...
使用JQuery-Week-Calendar做日程 -
xbliu564:
请问版本号
fusionchart 破解文件SWF -
xue_lang:
看了半天,有点坑爹的赶脚,哎
状态模式(State) -
teacup_madman:
我只能说。这个程序可以去掉的地方太多了。这个真的是State模 ...
状态模式(State) -
冬日的阳光:
TrafficLight这个类的change方法可以改一下,如 ...
状态模式(State)
首先我们先看看一个例子,在说什么是单利模式(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; } }
不过这种简单的写法不适合用于像服务器这种服务很多线程的程序上,同步机制会造成相当的效能低落,为了顾及Singleton、Lazy 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; } }
也就是只有在第一次建立实例时才会进入同步区,之后由于实例已建立,也就不用进入同步区进行锁定。Java中Runtime类别的作法简单的多, 它舍弃了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;
}
}
再次感谢各位朋友的关注!
评论
public class Singleton { static class SingletonHolder { static Singleton instance = new Singleton(); } public static Singleton getInstance() { return SingletonHolder.instance; } }
怎么还这么多人不知道这个?老早就在je看到过了
参见http://en.wikipedia.org/wiki/Initialization_on_demand_holder_idiom
个人理解:
原因:类在调用getInstance方法才会初始化(并非实例化)SingletonHolder,并且该过程是由jvm来保证其单线程执行的
sun的初始化的描述
A class or interface type T will be initialized immediately before the first occurrence of any one of the following:
T is a class and an instance of T is created.
T is a class and a static method declared by T is invoked.
A static field declared by T is assigned.
A static field declared by T is used and the field is not a constant variable (§4.12.4).
T is a top-level class, and an assert statement (§14.10) lexically nested within T is executed.
<div class="quote_div">
<div class="quote_title">gstarwd 写道</div>
<div class="quote_div">
<div class="quote_title">BestUpon 写道</div>
<div class="quote_div">
<div class="quote_title">gstarwd 写道</div>
<div class="quote_div">
<div class="quote_title">“new Singleton()不是一个atomic的操作。 ”<br><br>这样的操作在java中多么?<br>
</div>
<div class="quote_title"><br></div>
<p><span style="color: #ff0000;"><strong>为什么这个能保证延迟加载呢?</strong></span></p>
<div class="quote_title">BestUpon 写道</div>
<div class="quote_div">
<pre name="code" class="java">/**
*<span style="line-height: 19px; font-family: verdana,nsimsun,sans-serif; white-space: normal;"><a style="color: #5c81a7;" name="code10"><strong>使用 static 字段的单例实现</strong></a></span>
**/
class Singleton
{
private Vector v;
private boolean inUse;
private static Singleton instance = new Singleton();<span style="color: #ff0000;"><strong>//这个为什么能保证延迟加载呢》?</strong></span>
private Singleton()
{
v = new Vector();
inUse = true;
//...
}
public static Singleton getInstance()
{
return instance;
}
}</pre>
<p> </p>
</div>
</div>
<p> </p>
<p> </p>
<p>这个不能保证是延迟加载,而是饿汉方式!是为了解决双重锁定问题!</p>
</div>
<p>那么这个 为什么能呢?(我是提问的语气哦。。。不是反问的语气 - =)</p>
<pre name="code" class="java">public class Singleton {
static class SingletonHolder {
static Singleton instance = new Singleton();
}
public static Singleton getInstance() {
return SingletonHolder.instance;
}
}
</pre>
</div>
<p> </p>
<p> </p>
<p>你说的这种写法我也是第一次见:我的理解是这样的</p>
<p> </p>
<pre name="code" class="java">public class Singleton {
static class SingletonHolder { //静态内部类
static Singleton instance = new Singleton();
}
public static Singleton getInstance() {
return SingletonHolder.instance;
}
}</pre>
<p> 静态类在一开始就初始化好了,并且该静态类包含在<span style="white-space: pre;">Singleton这个类中,调用</span><span style="white-space: pre;"> getInstance()的时候返回的是</span><span style="white-space: pre;">SingletonHolder.instance;这个过程是相对而言的,意思是说,</span><span style="white-space: pre;">Singleton 这个类没有在初始化的时候</span></p>
<p>创建对象,而是创建了一个内部类的<span style="white-space: pre;">SingletonHolder,让他去创建</span><span style="white-space: pre;">Singleton的一个对象,这样在思维和逻辑上,</span><span style="white-space: pre;">Singleton</span><span style="white-space: pre;">在初始化的时候没有创建对象,而是在get的时候才创建对象的。</span></p>
<p>我觉得是相对而言,思维上的理解,不是绝对的没有创建对象,也不是绝对的延迟加载!不知道我理解的对不对!还望大家指教!</p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<div><br></div>
<p> </p>
</div>
<p>我认为应该是延迟加载(当然我不知道对不对,如果错了,请大家指出来):首先jvm在启动的时候不会加载 SingletonHolder 这个静态内部类,也就说程序先执行</p>
<p>getInstance(),然后转到 SingletonHolder.instance()里面,然后方法里面有 new关键字,也就是jvm在这个时候加载 Singleton ,所以我觉得应该是延迟加载</p>
<p> </p>
public class Singleton { static class SingletonHolder { static Singleton instance = new Singleton(); } public static Singleton getInstance() { return SingletonHolder.instance; } }
这个的确牛
Apache就是这么实现的,不过SingletonHolder是私有内部静态类...
当然如果classloader使用了二次.....这个也是不安全的.
<div class="quote_div">
<div class="quote_title">BestUpon 写道</div>
<div class="quote_div">
<div class="quote_title">gstarwd 写道</div>
<div class="quote_div">
<div class="quote_title">“new Singleton()不是一个atomic的操作。 ”<br><br>这样的操作在java中多么?<br>
</div>
<div class="quote_title"><br></div>
<p>
<span style="color: #ff0000;"><strong>为什么这个能保证延迟加载呢?</strong></span></p>
<div class="quote_title">BestUpon 写道</div>
<div class="quote_div">
<pre name="code" class="java">/**
*<span style="white-space: normal; line-height: 19px; font-family: verdana,nsimsun,sans-serif;"><a style="color: #5c81a7;" name="code10"><strong>使用 static 字段的单例实现</strong></a></span>
**/
class Singleton
{
private Vector v;
private boolean inUse;
private static Singleton instance = new Singleton();<span style="color: #ff0000;"><strong>//这个为什么能保证延迟加载呢》?</strong></span>
private Singleton()
{
v = new Vector();
inUse = true;
//...
}
public static Singleton getInstance()
{
return instance;
}
}</pre>
<p> </p>
</div>
</div>
<p> </p>
<p> </p>
<p>这个不能保证是延迟加载,而是饿汉方式!是为了解决双重锁定问题!</p>
</div>
<p>那么这个 为什么能呢?(我是提问的语气哦。。。不是反问的语气 - =)</p>
<pre name="code" class="java">public class Singleton {
static class SingletonHolder {
static Singleton instance = new Singleton();
}
public static Singleton getInstance() {
return SingletonHolder.instance;
}
}
</pre>
</div>
<p> </p>
<p> </p>
<p>你说的这种写法我也是第一次见:我的理解是这样的</p>
<p> </p>
<pre name="code" class="java">public class Singleton {
static class SingletonHolder { //静态内部类
static Singleton instance = new Singleton();
}
public static Singleton getInstance() {
return SingletonHolder.instance;
}
}</pre>
<p> 静态类在一开始就初始化好了,并且该静态类包含在<span style="white-space: pre;">Singleton这个类中,调用</span><span style="white-space: pre;"> getInstance()的时候返回的是</span><span style="white-space: pre;">SingletonHolder.instance;这个过程是相对而言的,意思是说,</span><span style="white-space: pre;">Singleton 这个类没有在初始化的时候</span></p>
<p>创建对象,而是创建了一个内部类的<span style="white-space: pre;">SingletonHolder,让他去创建</span><span style="white-space: pre;">Singleton的一个对象,这样在思维和逻辑上,</span><span style="white-space: pre;">Singleton</span><span style="white-space: pre;">在初始化的时候没有创建对象,而是在get的时候才创建对象的。</span></p>
<p>我觉得是相对而言,思维上的理解,不是绝对的没有创建对象,也不是绝对的延迟加载!不知道我理解的对不对!还望大家指教!</p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<div><br></div>
<p> </p>
<div class="quote_div">
<div class="quote_title">gstarwd 写道</div>
<div class="quote_div">
<div class="quote_title">“new Singleton()不是一个atomic的操作。 ”<br><br>这样的操作在java中多么?<br>
</div>
<div class="quote_title"><br></div>
<p>
<span style="color: #ff0000;"><strong>为什么这个能保证延迟加载呢?</strong></span></p>
<div class="quote_title">BestUpon 写道</div>
<div class="quote_div">
<pre name="code" class="java">/**
*<span style="white-space: normal; line-height: 19px; font-family: verdana,nsimsun,sans-serif;"><a style="color: #5c81a7;" name="code10"><strong>使用 static 字段的单例实现</strong></a></span>
**/
class Singleton
{
private Vector v;
private boolean inUse;
private static Singleton instance = new Singleton();<span style="color: #ff0000;"><strong>//这个为什么能保证延迟加载呢》?</strong></span>
private Singleton()
{
v = new Vector();
inUse = true;
//...
}
public static Singleton getInstance()
{
return instance;
}
}</pre>
<p> </p>
</div>
</div>
<p> </p>
<p> </p>
<p>这个不能保证是延迟加载,而是饿汉方式!是为了解决双重锁定问题!</p>
</div>
<p>那么这个 为什么能呢?(我是提问的语气哦。。。不是反问的语气 - =)</p>
<pre name="code" class="java">public class Singleton {
static class SingletonHolder {
static Singleton instance = new Singleton();
}
public static Singleton getInstance() {
return SingletonHolder.instance;
}
}
</pre>
<div class="quote_div">
<div class="quote_title">“new Singleton()不是一个atomic的操作。 ”<br><br>这样的操作在java中多么?<br>
</div>
<div class="quote_title"><br></div>
<p>
<span style="color: #ff0000;"><strong>为什么这个能保证延迟加载呢?</strong></span></p>
<div class="quote_title">BestUpon 写道</div>
<div class="quote_div">
<pre name="code" class="java">/**
*<span style="white-space: normal; line-height: 19px; font-family: verdana,nsimsun,sans-serif;"><a style="color: #5c81a7;" name="code10"><strong>使用 static 字段的单例实现</strong></a></span>
**/
class Singleton
{
private Vector v;
private boolean inUse;
private static Singleton instance = new Singleton();<span style="color: #ff0000;"><strong>//这个为什么能保证延迟加载呢》?</strong></span>
private Singleton()
{
v = new Vector();
inUse = true;
//...
}
public static Singleton getInstance()
{
return instance;
}
}</pre>
<p> </p>
</div>
</div>
<p> </p>
<p> </p>
<p>这个不能保证是延迟加载,而是饿汉方式!是为了解决双重锁定问题!</p>
</div>
<div class="quote_title"><br></div>
<p>
<span style="color: #ff0000;"><strong>为什么这个能保证延迟加载呢?</strong></span></p>
<div class="quote_title">BestUpon 写道</div>
<div class="quote_div">
<pre name="code" class="java">/**
*<span style="white-space: normal; line-height: 19px; font-family: verdana,nsimsun,sans-serif;"><a style="color: #5c81a7;" name="code10"><strong>使用 static 字段的单例实现</strong></a></span>
**/
class Singleton
{
private Vector v;
private boolean inUse;
private static Singleton instance = new Singleton();<span style="color: #ff0000;"><strong>//这个为什么能保证延迟加载呢》?</strong></span>
private Singleton()
{
v = new Vector();
inUse = true;
//...
}
public static Singleton getInstance()
{
return instance;
}
}</pre>
<p> </p>
</div>
所谓的加载,是在程序一启动的时候加载还是在访问的时候加载!在程序一启动的时候就加载该类对象实例,该实例中包含的所有的有用信息,如果类很庞大的话,启动速度当然会很慢(对该类实例化耗费时间),而耗费了很大力气初始化好了该对象实例,但是用它的时候很迟很迟,可以说是在将来很长一段时间,都不会用到该类的实例,但是他却一直在contain中,是不是很耗资源呢?而在其访问的时候去加载它,虽然加载的时候会消耗一部分时间,但是换来了以前所有资源的节约,你说有没有必要实行延迟加载呢?
前车之鉴还是得学习的嘛!
new Singleton()不是一个atomic的操作。
你的instance可能处于一个不是null,但是又不是完整对象的状态。
这样会导致程序崩溃。
你说的很对!我以前没有意识到这一点,多线程没有想到线程的中断和独占问题!谢谢你的提醒!
兄台说的可见性,是否是使用声明称“Volatile ”?
public class Singleton { static class SingletonHolder { static Singleton instance = new Singleton(); } public static Singleton getInstance() { return SingletonHolder.instance; } }
这个的确牛
new Singleton()不是一个atomic的操作。
你的instance可能处于一个不是null,但是又不是完整对象的状态。
这样会导致程序崩溃。
发表评论
-
框架底层综合+快速开发+代码重用框架-设计(Action)层)
2010-09-20 18:15 1286框架底层综合+快速开发+代码重用框架-设计(Model层 ... -
框架底层综合+快速开发+代码重用框架-设计(Service)层)
2010-09-20 17:51 2314框架底层综合+快速开发+代码重用框架-设计(Mod ... -
框架底层综合+快速开发+代码重用框架-设计(Dao层)
2010-09-20 17:06 1667二、Dao层 Dao层是数据化持久层,以前我们习惯使用 ... -
框架底层综合+快速开发+代码重用框架-设计(Model层)
2010-09-19 20:26 1753框架底层综合+快速开发+代码重用框架-设计(Model层) ... -
状态模式(State)续谈
2010-06-18 00:49 1432前面写了一片文章:状态模式(state)http://best ... -
状态模式(State)
2010-06-17 10:43 6051请参看:状态模式续. http://bestupon.i ... -
原型模式(Prototype)
2010-06-13 09:59 1198原型模式: 1、定义:原型模式就是通过一个原型对象来 ... -
责任链模式一
2010-01-26 16:42 1603责任链模式(Chain of Responsibility)是 ... -
创建者模式(Builder)
2009-09-29 12:32 1430创建者模式:(builder) 1、定义:创建者模式就是将一个 ... -
总结几个工厂模式
2009-09-28 11:29 1107总结几个工厂模式: 1、简单工厂模式:由一个类来负责所有的产品 ... -
抽象工厂模式
2009-09-28 11:20 1350package org.bestupon.abstratf ... -
工厂方法模式
2009-09-27 15:07 874工厂方法模式: 定义:工厂方法模式是用于创建对象的接口,让子 ... -
简单工厂模式
2009-09-27 14:19 1258简单工厂模式又叫静 ...
相关推荐
简单的单例模式举例Singleton 分为恶汉式 懒汉式
单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。 这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个...
单例模式的特点有三: 单例类只能有一个实例。 单例类必须自己创建自己的唯一实例。 单例类必须给所有其他对象提供这一实例。 Singleton模式包含的角色只有一个,就是Singleton。Singleton拥有一个私有构造函数,...
单例模式(Singleton)
该文当中对Java单类模式有非常细致入微的,循序渐进的讲解。
单例模式 Singleton 单例模式线程安全问题和拓展
设计模式C++学习之单例模式(Singleton)
主要介绍了单例模式 Singleton 简单实例设计模式解析的相关资料,需要的朋友可以参考下
java Singleton单例模式 java Singleton单例模式
一个产生随机数的例子,整个应用程序中只需要一个类的实例来产生随机数,客户端程序从类中获取这个实例,调用这个实例的方法nextInt(),公用的方法访问需要进行同步,这是单例模式需要解决的同步问题。
此示例展示了Qml 的单例模式(类似全局对象,只生成一次实例,可全局使用) surfsky.cnblogs.com
单例模式 Singleton Pattern 问题解决: (1)单例模式简介: Singleton模式要求一个类有且仅有一个实例,并且提供了一个全局的访问点。这就提出了一个问题:如何绕过常规的构造器,提供一种机制来保证一个类只有...
Java面向对象(高级)-- 单例(Singleton)设计模式
单例模式(Singleton)的6种实现,单例模式(Singleton)的6种实现
设计模式总结-模板设计模式,单例模式(singleTon)
在Java应用中,单例对象能保证在一个...3、有些像交易所的核心交易引擎,控制着交易流程,如果该类可以创建多个的话,系统完全乱了,只有使用单例模式,才能保证核心交易服务器独立控制整个流程。 CSDN代码的详细解释。
4、单例模式(Singleton Pattern) 用意:仅允许生成一个对象时
深入浅出Singleton,详细掌握单例模式
单例设计模式Singleton1