- 浏览: 7250927 次
- 性别:
- 来自: 上海
文章分类
- 全部博客 (1546)
- 企业中间件 (236)
- 企业应用面临的问题 (236)
- 小布Oracle学习笔记汇总 (36)
- Spring 开发应用 (54)
- IBatis开发应用 (16)
- Oracle基础学习 (23)
- struts2.0 (41)
- JVM&ClassLoader&GC (16)
- JQuery的开发应用 (17)
- WebService的开发应用 (21)
- Java&Socket (44)
- 开源组件的应用 (254)
- 常用Javascript的开发应用 (28)
- J2EE开发技术指南 (163)
- EJB3开发应用 (11)
- GIS&Mobile&MAP (36)
- SWT-GEF-RCP (52)
- 算法&数据结构 (6)
- Apache开源组件研究 (62)
- Hibernate 学习应用 (57)
- java并发编程 (59)
- MySQL&Mongodb&MS/SQL (15)
- Oracle数据库实验室 (55)
- 搜索引擎的开发应用 (34)
- 软件工程师笔试经典 (14)
- 其他杂项 (10)
- AndroidPn& MQTT&C2DM&推技术 (29)
- ActiveMQ学习和研究 (38)
- Google技术应用开发和API分析 (11)
- flex的学习总结 (59)
- 项目中一点总结 (20)
- java疑惑 java面向对象编程 (28)
- Android 开发学习 (133)
- linux和UNIX的总结 (37)
- Titanium学习总结 (20)
- JQueryMobile学习总结 (34)
- Phonegap学习总结 (32)
- HTML5学习总结 (41)
- JeeCMS研究和理解分析 (9)
最新评论
-
lgh1992314:
[u][i][b][flash=200,200][url][i ...
看看mybatis 源代码 -
尼古拉斯.fwp:
图片根本就不出来好吧。。。。。。
Android文件图片上传的详细讲解(一)HTTP multipart/form-data 上传报文格式实现手机端上传 -
ln94223:
第一个应该用排它网关吧 怎么是并行网关, 并行网关是所有exe ...
工作流Activiti的学习总结(八)Activiti自动执行的应用 -
ZY199266:
获取不到任何消息信息,请问这是什么原因呢?
ActiveMQ 通过JMX监控Connection,Queue,Topic的信息 -
xiaoyao霄:
DestinationSourceMonitor 报错 应该导 ...
ActiveMQ 通过JMX监控Connection,Queue,Topic的信息
本文将探讨单例模式的各种情况,并给出相应的建议。 单例模式应该是设计模式中比较简单的一个,但是在多线程并发的环境下使用却是不那么简单了。
首先看最原始的单例模式。
2
3 public class Singleton {
4
5 private static Singleton instance = null;
6
7 private Singleton() {
8 }
9
10 public static Singleton getInstance() {
11 if (instance == null) {
12 instance = new Singleton();
13 }
14 return instance;
15 }
16 }
17
显然这个写法在单线程环境下非常好,但是多线程会导致多个实例出现,这个大家都能理解。
最简单的改造方式是添加一个同步锁。
2
3 public class SynchronizedSingleton {
4
5 private static SynchronizedSingleton instance = null;
6
7 private SynchronizedSingleton() {
8 }
9
10 public static synchronized SynchronizedSingleton getInstance() {
11 if (instance == null) {
12 instance = new SynchronizedSingleton();
13 }
14 return instance;
15 }
16 }
17
显然上面的方法避免了并发的问题,但是由于我们只是在第一次构造对象的时候才需要同步,以后就不再需要同步,所以这里不可避免的有性能开销。于是将锁去掉采用静态的属性来解决同步锁的问题。
2
3 public class StaticSingleton {
4
5 private static StaticSingleton instance = new StaticSingleton();
6
7 private StaticSingleton() {
8 }
9
10 public static StaticSingleton getInstance() {
11 return instance;
12 }
13 }
14
上面的方法既没有锁又解决了性能问题,看起来已经满足需求了。但是追求“完美”的程序员想延时加载对象,希望在第一次获取的时候才构造对象,于是大家非常聪明的进行改造,也即非常出名的双重检查锁机制出来了。
2
3 public class DoubleLockSingleton {
4
5 private static DoubleLockSingleton instance = null;
6
7 private DoubleLockSingleton() {
8 }
9
10 public static DoubleLockSingleton getInstance() {
11 if (instance == null) {
12 synchronized (DoubleLockSingleton.class) {
13 if (instance == null) {
14 instance = new DoubleLockSingleton();
15 }
16 }
17 }
18 return instance;
19 }
20 }
21
双重锁机制看起来非常巧妙的避免了上面的问题。但是真的是这样的吗?文章《双重检查锁定及单例模式》中谈到了非常多演变的双重检查锁机制带来的问题,包括比较难以理解的指令重排序机制等。总之就是双重锁机制仍然对导致错误问题而不是性能问题。
于是继续改造,某个牛人利用JVM的特性来解决上述问题,具体哪个牛人我忘记了,但是不是下面文章的作者。
(1)《Java theory and practice: Fixing the Java Memory Model, Part 2》
(2)《Initialize-On-Demand Holder Class and Singletons》
2
3 public class HolderSingleton {
4
5 private static class HolderSingletonHolder {
6
7 static HolderSingleton instance = new HolderSingleton();
8 }
9
10 private HolderSingleton() {
11 //maybe throw an Exception when doing something
12 }
13
14 public static HolderSingleton getInstance() {
15 return HolderSingletonHolder.instance;
16 }
17 }
18
上述代码看起来解决了上面单例模式遇到的所有问题,而且实际上工作的很好,没有什么问题。但是却有一个致命的问题,如果第11行抛出了一个异常,也就是第一次构造函数失败将导致永远无法再次得到构建对象的机会。
使用下面的代码测试下。
2
3 public class HolderSingletonTest {
4
5 private static class HolderSingletonHolder {
6
7 static HolderSingletonTest instance = new HolderSingletonTest();
8 }
9
10 private static boolean init = false;
11
12 private HolderSingletonTest() {
13 //maybe throw an Exception when doing something
14 if(!init) {
15 init=true;
16 throw new RuntimeException(“fail“);
17 }
18 }
19
20 public static HolderSingletonTest getInstance() {
21 return HolderSingletonHolder.instance;
22 }
23 public static void main(String[] args) {
24 for(int i=0;i<3;i++) {
25 try {
26 System.out.println(HolderSingletonTest.getInstance());
27 } catch (Exception e) {
28 System.err.println(“one->“+i);
29 e.printStackTrace();
30 }catch(ExceptionInInitializerError err) {
31 System.err.println(“two->“+i);
32 err.printStackTrace();
33 }catch(Throwable t) {
34 System.err.println(“three->“+i);
35 t.printStackTrace();
36 }
37 }
38 }
39 }
40
很不幸将得到以下输出:
two->0
java.lang.ExceptionInInitializerError
at xylz.study.singleton.HolderSingletonTest.getInstance(HolderSingletonTest.java:21)
at xylz.study.singleton.HolderSingletonTest.main(HolderSingletonTest.java:26)
Caused by: java.lang.RuntimeException: fail
at xylz.study.singleton.HolderSingletonTest.<init>(HolderSingletonTest.java:16)
at xylz.study.singleton.HolderSingletonTest.<init>(HolderSingletonTest.java:12)
at xylz.study.singleton.HolderSingletonTest$HolderSingletonHolder.<clinit>(HolderSingletonTest.java:7)
… 2 more
three->1
java.lang.NoClassDefFoundError: Could not initialize class xylz.study.singleton.HolderSingletonTest$HolderSingletonHolder
at xylz.study.singleton.HolderSingletonTest.getInstance(HolderSingletonTest.java:21)
at xylz.study.singleton.HolderSingletonTest.main(HolderSingletonTest.java:26)
three->2
java.lang.NoClassDefFoundError: Could not initialize class xylz.study.singleton.HolderSingletonTest$HolderSingletonHolder
at xylz.study.singleton.HolderSingletonTest.getInstance(HolderSingletonTest.java:21)
at xylz.study.singleton.HolderSingletonTest.main(HolderSingletonTest.java:26)
很显然我们想着第一次加载失败第二次能够加载成功,非常不幸,JVM一旦加载某个类失败将认为此类的定义有问题,将来不再加载,这样就导致我们没有机会再 加载。目前看起来没有办法避免此问题。如果要使用JVM的类加载特性就必须保证类加载一定正确,否则此问题将比并发和性能更严重。如果我们的类需要初始话 那么就需要想其它办法避免在构造函数中完成。看起来像是又回到了老地方,难道不是么?
总之,结论是目前没有一个十全十美的单例模式,而大多数情况下我们只需要满足我们的需求就行,没必有特意追求最“完美”解决方案。
发表评论
-
Mule ESB 学习笔记(20)Mule和Spring httpinvoker的整合
2013-08-28 13:59 3662mule的配置文件: <?xml version=& ... -
Mule ESB 学习笔记(19)Mule和RSS的整合
2013-08-28 10:08 2516定时扫描特定目录的rss文件: <?xml vers ... -
Mule ESB 学习笔记(18)Mule和ATOM的整合
2013-08-27 20:00 2528定时读取特定文件的rss文件: <?xml ... -
Mule ESB 学习笔记(17)Mule和JMX的整合
2013-08-27 16:48 3975Agent的实现: package com.easyway ... -
Mule ESB 学习笔记(16)CXF SOAP基于SAML的验证的配置
2013-08-27 15:19 3716mule的配置 <mule xmlns:core=& ... -
Mule ESB 学习笔记(15)CXF SOAP基于JKS的验证的配置
2013-08-27 14:57 3763mule的配置如下: <mule xmlns:cor ... -
Mule ESB 学习笔记(14)CXF SOAP基于UsernameToken的验证
2013-08-27 14:16 7869简单需求: 针对在webservice ... -
Mule ESB 学习笔记(13)CSV数据文件到数据库
2013-08-26 17:54 6954简单需求: ... -
Mule ESB 学习笔记(12)JSON转换器的使用
2013-08-26 13:54 8960在许多情况下,可能需要把类转换为js ... -
Mule ESB 学习笔记(11)Web Service Proxy
2013-08-24 19:32 6514一、WebSevice Proxy 简介 ... -
Mule ESB 学习笔记(10)mule事务配置
2013-08-23 16:36 6106在mule的事务可能为jdbc事务,jms事务 ... -
Mule ESB 学习笔记(9)mule配置常用节点解释
2013-08-23 13:27 33221 Mule-config.x ... -
Mule ESB 学习笔记(8)mule和jersey的整合使用
2013-08-23 11:20 3858在项目常用jesery作为rest ... -
Mule ESB 学习笔记(7)服务调用
2013-08-23 10:44 18804一. 服务调用 1. Mule实现并提供Web Servi ... -
Mule ESB 学习笔记(6)配置模式
2013-08-23 10:42 4669为了节省时间,就不翻译了,摘抄重点总结 ... -
Mule ESB 学习笔记(5)异步请求-响应方式
2013-08-22 15:32 34875.4 异步请求-响应方式 异步请求-响应方式即请求方调用 ... -
Mule ESB 学习笔记(4)同步方式
2013-08-22 15:19 41185.3 同步方式 同步方式即请求方调用 ... -
JBOSS EJB3项目启动执行一个任务
2013-08-06 22:26 3722在jboss的项目中,jboss启动 ... -
Jboss @Service的使用
2013-08-06 21:59 1900Jboss有一个扩展的annotation——@Servic ... -
julian Date 计算 和实现
2013-08-01 09:32 4325Qt库里CBSDate类的内部实现用_jd成员进行计算、比较 ...
相关推荐
设计优雅 语言包存储格式为 xml 格式,和 res 下的 strings.xml 一致 零依赖,完全使用系统 api 和系统的 xml 解析器 不持有 context,无内存泄漏 静态方法 + 单例模式,一处安装,到处使用动态化语言包 动态下发...
report项目请求通道采用责任链模式设计,扩展性极强,流程完全可控! ankang-report report 是一个开源的访问层框架,基于java平台,依赖于spring,以Mozilla Public License 2.0 协议发布。可用于接口的调试及性能...
Struts1只是在第一次请求的时候创建一个action实例,以后每次相同的请求都直接从内存中去读取,它是单例模式,安全性较差。 Struts2是如何实现MVC模式的? 答:在Struts2里面是将每次页面的请求进行处理,然后将请求...
面向对象计算始于这个基本概念,即现实世界可以被描绘成一系列完全自治、封装的对象,这些对象通过一个受保护的接口访问其他对象。 4. 多态性: 多态性是指允许不同类的对象对同一消息作出响应。多态性包括参数化...
面向对象计算始于这个基本概念,即现实世界可以被描绘成一系列完全自治、封装的对象,这些对象通过一个受保护的接口访问其他对象。 4. 多态性: 多态性是指允许不同类的对象对同一消息作出响应。多态性包括参数化多...
3.容器提供单例模式支持 4.容器提供了AOP技术,利用它很容易实现如权限拦截,运行期监控等功能 5.容器提供了众多的辅助类,能加快应用的开发 6.spring对于主流的应用框架提供了集成支持,如hibernate,JPA,...
综上所述,“认我测”在线认证检测系统,率先填补了认证检测领域移动端的空缺,提供了Web浏览器+移动端的双端访问模式,给用户提供了多种访问途径,真正实现了用户和检测机构的随时随地在线下单检测。 关键词:...
原文如下: 以前写了一个java的正规表达式的java工具类,分享一下,有用到的欢迎下载使用。 如果你有常用的定义好的,且测试通过的正规表达式,欢迎跟贴,也让我享用一下 . 类中用到了 jakarta-oro-2.0.jar 包,请...