网络编程 | 站长之家 | 网页制作 | 图形图象 | 操作系统 | 冲浪宝典 | 软件教学 | 网络办公 | 邮件系统 | 网络安全 | 认证考试 | 系统进程
Firefox | IE | Maxthon | 迅雷 | 电驴 | BitComet | FlashGet | QQ | QQ空间 | Vista | 输入法 | Ghost | Word | Excel | wps | Powerpoint
asp | .net | php | jsp | Sql | c# | Ajax | xml | Dreamweaver | FrontPages | Javascript | css | photoshop | fireworks | Flash | Cad | Discuz!
当前位置 > 网站建设学院 > 网络编程 > Java
Tag:注入,存储过程,分页,安全,优化,xmlhttp,fso,jmail,application,session,防盗链,stream,无组件,组件,md5,乱码,缓存,加密,验证码,算法,cookies,ubb,正则表达式,水印,索引,日志,压缩,base64,url重写,上传,控件,Web.config,JDBC,函数,内存,PDF,迁移,结构,破解,编译,配置,进程,分词,IIS,Apache,Tomcat,phpmyadmin,Gzip,触发器,socket
网络编程:ASP教程,ASP.NET教程,PHP教程,JSP教程,C#教程,数据库,XML教程,Ajax,Java,Perl,Shell,VB教程,Delphi,C/C++教程,软件工程,J2EE/J2ME,移动开发
本月文章推荐
.java指南之使用图形:概览.
.深入了解WebLogic的类装载机制详.
.在Java编程中的“模式思想”与框.
.Servlets在网站中的应用前景如何.
.jdk1.4_01实现Applet的数字签名认.
.Spirng下的log4j设置 [引用].
.JAVA学习,是一条漫长的道路.
.探索J2ME:创建开销细节表单.
.使用Java来监视系统进程的两个解.
.如何规划您的大型JAVA多并发服务.
.取余赋值运算符 (%=).
.JBOSS4数据源配置大全(二).
.JDBC系列教程(四)---结果设置.
.用Javamail写的邮件接收程序.
.J2ME综合-J2ME应用程序内存优化.
.Java动画编程基础第二部分.
.SWT:实现自我绘制的Button组件.
.实例讲解Spring集成JSF的最简单方.
.J2ME程序开发全方位基础讲解汇总.
.前车之覆,后车之鉴 --开源项目经.

谨慎使用类变量及正确使用单例模式

发表日期:2008-1-5



CowNew开源团队网站 http://www.cownew.com 
论坛 http://www.cownew.com/newpeng/ 
转载请注明此版权信息 
        
        昨天发现JDBMonitor在多数据源的情况下会有问题,这个问题就是对单例模式理解不深造成的。为了减少系统中的对象数目,我用单例模式设计DBLogger,也就是提供一个getLogger方法返回一个日志处理器,getLogger则返回的是一个缓存了的DBLogger实例。昨天我用一个大型的信息系统测试了一下,发现当有多个数据源存在的时候,所有的日志都记录到了第一个启动的JDBMonitor的配置文件指定的监听器中了。经过分析得知,虽然多个数据源启动了多个JDBMonitor,但是由于这些JDBMonitor实例是运行在同一个JVM中的,而一个类变量在同一个JVM是唯一的,所以这些实例调用getLogger的时候得到的都是第一个JDBMonitor中配置的了。
        我采用如下方式解决:为getLogger增加一个connectionId参数,将原先的单例去掉,改成一个hash表的静态变量instanceMap。在调用getLogger的时候,先以connectionId为key到instanceMap中找是不是已经有一个实例了,假如有则直接返回这个实例,否则构造一个DBLogger,将此DBLogger以connectionId为key保存到instanceMap中,然后返回实例。
        根据JDBMonitor的功能特点配置文件的路径就可以做为这个connectionId了,也就是假如是多个数据源指向一个配置文件,那么这几个数据源其实还是共用一个DBLogger,这个也是合理的,而且也可以节省很多资源。
        从这个例子我们可以看出,单例模式并不一定是只创建一个实例这么简单。Log4j的getLogger就是很好的证实。
        但是多个数据源共用一个DBLogger又引来了另一个问题,就是当有一个数据源的Connection被close掉以后,DBLogger也会随之close掉,其他数据源再访问的时候就会报错。我采用类似GC、COM等的引用机制解决此问题。在DBLogger内部维护一个计数器refCounter,初始值是0,当调用getLogger访问到此实例的时候,就refCounter自动加1,当调用DBLogger的close的时候就自动减1,当refCounter降到0的时候就说明没有对象引用到它了,这个时候再释放DBLogger中的各种资源。当然addRef、releaseRef、close等方法都要标识成synchronized的。
        同理,以前的这些channel、dbListeners类变量也要改成实例变量。consumerthread也要改成实例变量,在close中再关闭这个线程。这样就保证了每一个JDBMonitor都有自己的消费者线程。
        为了使语意更加明确,我将getLogger重命名为createLogger。
        代码已经提交到CVS,今天晚些时候将打包放到团队网站上。
        向大家汇报,SQL解析引擎已经有阶段成果,强类型AST节点都已定义完毕,也已经可以生成最简单的CommonAST。
上一篇:把业务流程从操作中剥离出来 人气:531
下一篇:关于23种设计模式的有趣见解 人气:1272
浏览全部Java的内容 Dreamweaver插件下载 网页广告代码 祝你圣诞节快乐 2009年新年快乐