2009年8月6日星期四

[转]单例模式和static是两码事情

<<<<<本文转自JDao社区的牛人的回帖:http://www.jdon.com/jivejdon/thread/31851.html
的确说的很不错,牛人就是牛人!>>>>>

单例模式和static是两码事情,单例模式可以使用static实现,也可以不由其实现。

>那可能对象多了,单例在内存中就占了20M(假如,也许更多),那这样是得不到释放的,
这个现象是针对static而言的。我们可以让一个对象在内存是单例,但是当这样对象多了的时候,也可以释放,被GC清除。

这就涉及容器概念,也就是说,我们将这些对象单例用一个容器包容,不是直接将这些单例放到JVM,而是放到一个容器中,这个容器再放到JVM中;如果我们消灭这个容器对象,那么其中的单例对象就会被GC回收。

这个时候,单例概念已经不是原来JVM单例概念,这个单例是一定范围(时间或空间)内的单例,实际等同于对象的scope。

类似Spring/jdonFramework这样框架,就是引入了这样一个容器,如果我们将这个容器对象scope设置为Web的Application级别,也就是说,在某个Web项目中,这个容器是唯一的,那么容器中的单例对象也就是唯一。如果我们Web项目不再部署,退出,容器对象生命周期结束,其中所有单例对象生命周期也就结束。

注意:虽然我们变通了单例的生命周期,但是在单例有生命时段内,如果多个线程访问(写操作)单例中的状态,那么就有数据不一致问题,好事人如果在这个单例对状态访问操作加上同步锁,那么就可能将多线程的J2EE/JavaEE应用变成单线程。

所以,如果我们的服务或DAO都是无状态的,那么使用单例没有问题,但是谁能保证程序代码不修改,如果来个鲁莽的小伙子,将你的服务改成有状态,那么就出现很多奇怪问题了。

当然,如果你有一个称不上好习惯的习惯,不喜欢在类的字段中保存数据,什么都依赖数据库,那么使用单例也会一直没有问题,但是这种习惯是OO的吗?高负载下性能会好吗?这又涉及另外问题了。

所以,养成用多例Pool来支持你的服务,不失为一个克服上面的两全其美的好办法,但是POOL也有小的性能开销。

其实绕来绕去,我们发现:当初我们使用EJB时的最大困惑:有态和无态的选择,在Spring/jdonFramework中不是被消灭了,而是被转移了,表面简化了,但是这个问题永远回避不了。

没有评论: