- 浏览: 64392 次
- 性别:
- 来自: 苏州
-
最近访客 更多访客>>
最新评论
-
yuankai:
to seer_lee
final LazySingleto ...
java设计模式全解[1]-单例模式 -
yisonghui:
支持下LZ的无私奉献,对我这种刚入门的人来说还是很通俗易懂的。 ...
java设计模式全解[3]-建造者模式 -
Uranus:
不知道楼主可不可以写一个关于PROTOTYPE模式的文章,我对 ...
java设计模式全解[3]-建造者模式 -
Uranus:
不知道楼主可不可以深入分析下PROTOTYPE模式,我对这个不 ...
java设计模式全解[4]-工厂方法模式 -
zmo_xu:
我的文章是参考某.net大老的设计模式写的 .我在系列文章的第 ...
java设计模式全解[3]-建造者模式
在网上找了很久都没有找到详细分析java 设计模式的 后来在网上找到个.net的 看了后决定 对C#的代码进行java本地化(借用下这个词,不知道把C#变java叫做什么) 不敢独享 拿来与大家分析,当作搬家到javaeye 后zmo_xu给大家的见面礼吧,还请各位高手不要耻笑区区在下(文章有自己的理解也有网上原文,如果你发现zmo_xu个文章里面设计到了你的文章的版权 敬请致电 zmo2xu@gmail.com 我会及时处理),好了言归正传
第1章 单件模式(Single Pattern)
概述
Singleton模式要求一个类有且仅有一个实例,并且提供了一个全局的访问点。这就提出了一个问题:如何绕过常规的构造器,提供一种机制来保证一个类只有一个实例?客户程序在调用某一个类时,它是不会考虑这个类是否只能有一个实例等问题的,所以,这应该是类设计者的责任,而不是类使用者的责任。
从另一个角度来说,Singleton模式其实也是一种职责型模式。因为我们创建了一个对象,这个对象扮演了独一无二的角色,在这个单独的对象实例中,它集中了它所属类的所有权力,同时它也肩负了行使这种权力的职责!
意图
保证一个类仅有一个实例,并提供一个访问它的全局访问点。
生活中的例子
这里这个方法已经线程安全了但是我们知道对一个方法进行线程安全资源消耗是非常大的我们更倾向于对代码的同步 修改后的代码
美国总统的职位是Singleton,美国宪法规定了总统的选举,任期以及继任的顺序。这样,在任何时刻只能由一个现任的总统。无论现任总统的身份为何,其头衔"美利坚合众国总统"是访问这个职位的人的一个全局的访问点。
简单实现:最简单的实现就是在类内声明一个此类的实例并将构造函数私有化(为什么要用private而不用protected来保持可扩展性是因为 当类被继承后影响单例模式) 并向外公开一个getInstance()方法来获取这个实例集体实现 集体实现
java 代码
- package unit;
- public class Singletnon
- {
- private static Singletnon instance;
- private Singletnon()
- {
- }
- public static Singletnon getInstance()
- {
- if(instance==null)
- {
- instance=new Singletnon();
- }
- return instance;
- }
- }
大家可以看到这里的构造方法
是私有的,类外是无法访问的,就是说实现了限制实例化,但是一个类如果没有办法实例化那么这个类将什么也作不了 所以在这个类里面就的提供一个方法来实现实例化 也就是这里的getInstance将在类内对自己实例化并将实例传递出去,好了到此我们已经理解单例模式的实现,那么我们就要考虑安全问题 还有我们是不是真的实现了单例,其实这种模式在多线程模式下是不一定能实现单例模式的稍后我会在后面用一个例子来证明他,现在我们来考虑线程安全,你说synchronized ?,非常好 你已经抓住了问题的关键,我们接着往下走,修改后我们的代码变成了这样
- package unit;
- public class Singletnon
- {
- private static Singletnon instance;
- private Singletnon()
- {
- }
- public synchronized static Singletnon getInstance()
- {
- if(instance==null)
- {
- instance=new Singletnon();
- }
- return instance;
- }
- }
- package unit;
- public class Singletnon
- {
- private static Singletnon instance;
- private static final Object key = new Object();
- private Singletnon()
- {
- }
- public static Singletnon getInstance()
- {
- if (instance == null)
- {
- synchronized (key)
- {
- if (instance == null)
- {
- instance = new Singletnon();
- }
- }
- }
- return instance;
- }
- }
可以看到 zmo_xu在这里引入了一个Object 的对象key 为什么要引入一个key呢 用instance作为同步关键字不是更好吗!这个当然不行,因为线程同步锁锁定的是地址引用 如果你锁定的是instance的化 当你new的时候 地址引用就会改变.线程锁失效,额你说什么 不new 行不行..不new 不new.....不牛,我只能说这些想的人太牛了,要知道我们这里要保护的代码就是为了实例化,我们一定要牛(new)的拉!
单例模式就说到这里 下一次我们将介绍抽象工厂!
javastudy给出的代码补充在这里 !基本上思路是一样的 只是代码实现上有点区别
- //饿汉式:
- public class EagerSingleton {
- private EagerSingleton() { }
- public static EagerSingleton getInstance() {
- return m_instance;
- }
- /** @label Creates */
- private static final EagerSingleton m_instance = new EagerSingleton();
- }
- //懒汉式
- public class LazySingleton
- {
- private LazySingleton() { }
- synchronized public static LazySingleton getInstance()
- {
- if (m_instance == null)
- {
- m_instance = new LazySingleton();
- }
- return m_instance;
- }
- }
- //使用到才实例化 不使用不实例化,比如你使用此类的其他静态方法 而饿汉式只要用到就被实例化
- //登记式:
- import java.util.HashMap;
- public class RegSingletonChild extends RegSingleton
- {
- public RegSingletonChild() {}
- static public RegSingletonChild getInstance()
- {
- return (RegSingletonChild) RegSingleton.getInstance( "com.javapatterns.singleton.demos.RegSingletonChild" );
- }
- public String about()
- {
- return "Hello, I am RegSingletonChild.";
- }
- }
- //这个 嘿嘿 不太明白 待会去看看他的父类原代码
这个帖子的代码部分不会再修改了 就此代码部分封帖 ,希望大家 一起继续讨论共同提高
最后附上所有原代码
- Singleton.rar (4.9 KB)
- 描述: 单例模式的测试代码
- 下载次数: 166
评论
final LazySingleton temp = new LazySingleton(); instance = temp;
java语言规范规定:final引用被赋值给另一个引用时必须被完整初始化,即instance = temp肯定会在初始化构造函数结束后发生.
这个好像不对吧?
final FinalTest fin = null;
FinalTest ft = null;
ft = fin;
我这样用也没有报错啊?
http://www.javaworld.com/javaworld/jw-02-2001/jw-0209-double.html?page=4
http://www.javaworld.com/javaworld/jw-02-2001/jw-0209-toolbox.html
http://www.javaworld.com/javaworld/jw-05-2001/jw-0525-double.html?page=1
java中,double check的线程安全性在某些情况下会被破坏。
非线程安全的几种情况:
1.优化编译器重排JVM字节码
此时可能导致instance = new Singletnon()的执行不像字面显示的那样,而是先创建一个对象,然后赋值给instance,最后执行<init>方法(即构造函数),
在这种情况下,一些线程可能看到赋完值的非null引用,而此时对象的构造函数还并没有被调用,即这些线程看到了脏的中间数据。
2.在多处理器共享存储器环境中,内存的更新不可见,
也可能导致一个线程看不到初始化线程的初始化最终结果,
而读取到中间状态的脏数据。
解决方法:
把instance设置为:private static volatile LazySingleton instance;
这样优化编译器就不会再对instance的赋值指令进行重排,
肯定是发生在<init>函数结束时,
在多处理器共享存储器环境下,也可以保证任何线程对instance的内存更新其他线程都可以看见
注意:
JSE5或者更高的版本中的Java Memory Model和Thread specification保证了上述解决方案的可行性,
在低版本中还会存在线程安全被破坏的情况。
详细可见参考资料:
http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html
文章详细的讲述了Double Checking方法在Java中的表现。
下面是自己给出的另一种基于final关键字的方案,
没经过实践检验,自己只是觉得从逻辑上应该是对的,
请大家指正!
class LazySingleton {
private static LazySingleton instance;
private LazySingleton() {
}
public LazySingleton getInstance() {
if (instance == null) {
synchronized(this) {
if (instance == null) {
final LazySingleton temp =
new LazySingleton();
instance = temp;
}
}
}
return instance;
}
}
final LazySingleton temp = new LazySingleton(); instance = temp;
java语言规范规定:final引用被赋值给另一个引用时必须被完整初始化,即instance = temp肯定会在初始化构造函数结束后发生
<strong>javastudy 写道:</strong><br/>
<div class='quote_div'>
<div class='quote_div'>
<p> <span class='keyword'>public</span><span> </span><span class='keyword'>synchronized</span><span> </span><span class='keyword'>static</span><span> Singletnon getInstance() </span> </p>
<li class='alt'><span> { </span> </li>
<li class=''><span> </span><span class='keyword'>if</span><span> (instance == </span><span class='keyword'>null</span><span>) </span> </li>
<li class='alt'><span> { </span> </li>
<li class=''><span> </span><span class='keyword'>synchronized</span><span> (key) </span> </li>
<li class='alt'><span> { </span> </li>
<li class=''><span> </span><span class='keyword'>if</span><span> (instance == </span><span class='keyword'>null</span><span>) </span> </li>
<li class='alt'><span> { </span> </li>
<li class=''><span> instance = </span><span class='keyword'>new</span><span> Singletnon(); </span> </li>
<li class='alt'><span> } </span> </li>
<li class=''><span> } </span> </li>
<li class='alt'><span> } </span> </li>
<li class='alt'>方法还是同步的啊 </li>
</div>
</div>
汉死了 好像是我手误 应该是这样
<div class='code_title'>java 代码</div>
<div class='dp-highlighter'>
<div class='bar'/>
<ol class='dp-j'>
<li class='alt'><span><span class='keyword'>public</span><span> </span><span class='keyword'>static</span><span> Singletnon getInstance() </span></span></li>
<li class=''><span> </span></li>
<li class='alt'><span> { </span></li>
<li class=''><span> </span><span class='keyword'>if</span><span> (instance == </span><span class='keyword'>null</span><span>) </span></li>
<li class='alt'><span> { </span></li>
<li class=''><span> </span><span class='keyword'>synchronized</span><span> (key) </span></li>
<li class='alt'><span> { </span></li>
<li class=''><span> </span><span class='keyword'>if</span><span> (instance == </span><span class='keyword'>null</span><span>) </span></li>
<li class='alt'><span> { </span></li>
<li class=''><span> instance = </span><span class='keyword'>new</span><span> Singletnon(); </span></li>
<li class='alt'><span> } </span></li>
<li class=''><span> } </span></li>
<li class='alt'><span> } </span></li>
<li class=''><span> retuen instance; </span></li>
<li class='alt'><span>} </span></li>
</ol>
</div>
<br/>
<br/>
<br/>
<br/>
另外顺便把你的代码引用到我的帖子里面去了

懒汉式,饿汉式,登记式
.......
到底是什么啦,说清楚点,最好像楼主那样把相应的代码贴出来,谢谢!
也欢迎高手,指出其中的不足,大家一起讨论会更好
<div class='quote_div'><font><blockquote dir='ltr' style='margin-right: 0px;'><font><font><font>
<p> </p>
<p><font/></p>
</font></font></font></blockquote></font>这里这个方法已经线程安全了但是我们知道对一个方法进行线程安全资源消耗是非常大的我们更倾向于对代码的同步 修改后的代码
<div class='code_title'>java 代码</div>
<div class='dp-highlighter'>
<div class='bar'/>
<ol class='dp-j'>
<li class='alt'><span><span class='keyword'>package</span><span> unit; </span></span> </li>
<li class=''><span> </span> </li>
<li class='alt'><span/><span class='keyword'>public</span><span> </span><span class='keyword'>class</span><span> Singletnon </span> </li>
<li class=''><span>{ </span> </li>
<li class='alt'><span> </span><span class='keyword'>private</span><span> </span><span class='keyword'>static</span><span> Singletnon instance; </span> </li>
<li class=''><span> </span> </li>
<li class='alt'><span> </span><span class='keyword'>private</span><span> </span><span class='keyword'>static</span><span> </span><span class='keyword'>final</span><span> Object key = </span><span class='keyword'>new</span><span> Object(); </span> </li>
<li class=''><span> </span> </li>
<li class='alt'><span> </span><span class='keyword'>private</span><span> Singletnon() </span> </li>
<li class=''><span> { </span> </li>
<li class='alt'><span> </span> </li>
<li class=''><span> } </span> </li>
<li class='alt'><span> </span> </li>
<li class=''><span> </span><span class='keyword'>public</span><span> </span><span class='keyword'>synchronized</span><span> </span><span class='keyword'>static</span><span> Singletnon getInstance() </span> </li>
<li class='alt'><span> { </span> </li>
<li class=''><span> </span><span class='keyword'>if</span><span> (instance == </span><span class='keyword'>null</span><span>) </span> </li>
<li class='alt'><span> { </span> </li>
<li class=''><span> </span><span class='keyword'>synchronized</span><span> (key) </span> </li>
<li class='alt'><span> { </span> </li>
<li class=''><span> </span><span class='keyword'>if</span><span> (instance == </span><span class='keyword'>null</span><span>) </span> </li>
<li class='alt'><span> { </span> </li>
<li class=''><span> instance = </span><span class='keyword'>new</span><span> Singletnon(); </span> </li>
<li class='alt'><span> } </span> </li>
<li class=''><span> } </span> </li>
<li class='alt'><span> } </span> </li>
<li class=''><span> </span><span class='keyword'>return</span><span> instance; </span> </li>
<li class='alt'><span> } </span> </li>
<li class=''><span>} </span> </li>
</ol>
</div>
</div>
<p><br/>
<br/>
话说用了两个<span class='keyword'>synchronized同步性能就会提高么?</span></p>
<p><span class='keyword'>感觉里面那个<span class='keyword'>synchronized</span><span> (key) 有画蛇添足之嫌.</span></span></p>
<p><span class='keyword'><span/></span></p>
<p><span class='keyword'><span>关于<span> Singleton 的线程安全问题,Effective JAVA里面已经讲的很清楚,可以用initialize-on-demand holder class:</span></span></span></p>
<p><span class='keyword'><span><span/></span></span></p>
<span class='keyword'><span><span><font>
<div class='code_title'>java 代码</div>
<div class='dp-highlighter'>
<div class='bar'/>
<ol class='dp-j'>
<li class='alt'><span><span class='keyword'>public</span><span> </span><span class='keyword'>class</span><span> Singleton { </span></span> </li>
<li class=''><span> </span> </li>
<li class='alt'><span> </span><span class='keyword'>private</span><span> </span><span class='keyword'>static</span><span> </span><span class='keyword'>class</span><span> SingletonHandler{ </span> </li>
<li class=''><span> </span> </li>
<li class='alt'><span> </span><span class='keyword'>static</span><span> </span><span class='keyword'>final</span><span> Singleton singleton =</span><span class='keyword'>new</span><span> Singleton(); </span> </li>
<li class=''><span> </span> </li>
<li class='alt'><span> } </span> </li>
<li class=''><span> </span> </li>
<li class='alt'><span> </span><span class='keyword'>private</span><span> Singleton (){} </span> </li>
<li class=''><span> </span> </li>
<li class='alt'><span> </span><span class='keyword'>public</span><span> </span><span class='keyword'>static</span><span> Singleton getInstance(){ </span> </li>
<li class=''><span> </span> </li>
<li class='alt'><span> </span><span class='keyword'>return</span><span> SingletonHandler.singleton; </span> </li>
<li class=''><span> </span> </li>
<li class='alt'><span> } </span> </li>
<li class=''><span> </span> </li>
<li class='alt'><span>} </span> </li>
</ol>
</div>
<p><br/>
</p>
</font></span></span></span>
<p><br/>
<br/>
</p>
相关推荐
设计模式全解 设计模式是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。毫无疑问,设计模式于己于他人于系统都是多...
在C#中,常见的设计模式包括单例模式(确保类只有一个实例)、工厂模式(提供创建对象的接口)、观察者模式(定义对象间的一对多依赖关系)、装饰器模式(动态地给对象添加新的行为)和策略模式(定义一系列算法,并...
设计模式是软件工程中的最佳实践,23种设计模式包括工厂模式、单例模式、装饰者模式等,这份文档详细介绍了这些模式的概念、应用场景和实现方式,对提升代码质量和可维护性大有裨益。 7. **java虚拟机详解_免费....
熟练掌握常见的设计模式,如单例、工厂、建造者、装饰者、适配器、观察者、策略、模板方法等,这些是解决实际问题的常用工具,体现了良好的代码组织和设计能力。 五、Spring框架 作为企业级应用开发的主流框架,...
最后,设计模式是软件工程中的重要概念,"c#语法解析和设计模式"可能详细阐述了一些常见设计模式在C#中的实现,如工厂模式、单例模式、观察者模式、装饰器模式、策略模式等。设计模式提供了解决特定问题的通用解决...
#### JS设计模式全解 - **定义**:在软件工程中,设计模式是一系列经过验证的解决方案,用于解决常见的设计问题。 - **JS常用设计模式**:包括工厂模式、单例模式、观察者模式等。 - **应用场景**:改善代码的可读性...
7. **设计模式**:项目中可能会使用到单例模式、工厂模式、观察者模式等经典设计模式,以提高代码的可读性和可维护性。 8. **异常处理**:了解如何在代码中正确地捕获和处理异常,确保程序的稳定运行。 9. **项目...
JS 设计模式全解 - **知识点介绍**:这部分资料专注于 JavaScript 设计模式的学习,可能包括但不限于单例模式、工厂模式、观察者模式、适配器模式等多种常见的设计模式。通过学习这些模式,开发者可以更好地组织和...