单例模式网络资源非常多,尤其感谢http://www.javaeye.com/topic/60179这里的分享。
在选择mvc框架的同时一直有个问题。
springMVC 看了很多帖子说,springMVC的action是单例的,所以性能要高。性能高很多?会造成什么问题?
我们知道struts2 的action是非单例的,在每次请求的时候都会创建一个实例action来处理请求。
那么他的性能存在了问题?struts2 是如何保证性能的?每次都创建了一个对象,垃圾回收问题呢?看了很多文章都没有很清楚的介绍,只是简单的拿来对比。无论是不是线程安全的,无论是不是单例,至少
在选择mvc框架的时候要考虑性能问题。如果说单例模式是高性能的,但是同时也会造成很多问题,相反
非单例解决了单例的问题,但对性能又造成了多少影响?那么我们在选择的时候就需要有取舍,这个取舍是
如何评定的?拿出来讨论,期待高手解释。

解决方案 »

  1.   

    这点影响可以忽略。Servlet 也是个单实例的。所有单实例中不允许出现带有状态的成员变量。
      

  2.   

    单例模式我曾看过网上java的说法(我其实学。net的)说其实单例模式java没有完美解决方案。呵呵,我只知道一个简单的
      

  3.   

    不知道,一般解决性能问题都从代码和sql优化上着手
      

  4.   

    Web框架中很多对象都是单例的,主要是那些为用户请求服务的Object往往是单例。因为如果现在有100人访问你的Server,那么像Servlet,Action这类的对象就生产100个。
    那将是对内存和时间的极大浪费。(new是比较耗费的一种操作,要锁,从JVM堆中分配内存,创建对象。)最大的问题是,HTTP是无状态的,那么相应的request-response结构,就往往应该是无状态的。
    所以单例(往往)足够了。
      

  5.   

    不是很清楚也许struts2和EJB的无状态会话bean一样有个实例池,这样也许就不用每个request创建一个action instance了
      

  6.   


    按照火龙的说法,struts2是舍弃了这个单例的性能,为了解决单例中成员变量的状态问题?
    那struts2通过拦截器链来过滤所有的请求后,生成处理信息的action,可能会有很多action实例对象来等待回收,这点是不是也对性能造成了很大的影响呢?
    java确实没有特别好的解决单例问题的办法。尤其是多线程的时候,存在着诸多问题。需要我们调整和做取舍。顺便问火龙一个问题,gc是通过判断这个对象是否被使用来对对象回收的。到底这个对象是否被使用是如何判断的?
      

  7.   

    我比较赞同这个说法,其实我觉得虽然struts1和servlet-api耦合,但是其实就算改变了模式,相应的request-response结构这个结构还是没办法改变的。
      

  8.   

    struts2 的action 不能用单例模式,因为action相当于struts1里面的form一样了,所以没办法用单例模式。虽然spring的mvc没用过,但是两者最大的区别在表现层上。而且对于jdk1.5以后的版本来说,单例模式和 非单例模式在虚拟机里面已经做了很多优化,所以 单单从 单例模式 这个角度来比较效率是没意思的。而从根本上来说 ,导致struts2 效率变慢的原因还是因为自己的 tag,所以只要对一些tag使用上斟酌一下,效率不会是大问题,比如你用struts2的 动态树, sx:tree 必须引入 dojo,虽然jsp代码不多,但是生成html文件之后你会发现页面代码中添加了很多很多的js和css样式, 当树比较大的时候就会发现浏览器变得很卡。这点深有体会啊。但是其实用dtree完全可以实现这个动态树并且能够增加更多的css。
    还有就是 用dojo 和 json等结合实现动态级联,这个暂时在一些浏览器下面还不支持,所以说关键在于一些struts2自带的扩展功能上,这些功能为了能够尽可能的变得通用,增加了很多很多不必要的判断和限制条件,所以降低了效率。=====================单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。所以使用单例模式的目的不是为了减少  对象创建带来的资源问题, 而是为了保证对象的唯一性。
    spring3的mvc 和struts2 比较:
    spring mvc是方法级别的拦截,一个方法对应一个request上下文,而方法同时又跟一个url对应,所以说从架构本身上 spring3 mvc就容易实现restful url。
    struts2是类级别的拦截, 一个类对应一个request上下文;实现restful url要费劲,因为struts2 action的一个方法可以对应一个url。
    spring3 mvc的方法之间基本上独立的,独享request response数据,请求数据通过参数获取,处理结果通过ModelMap交回给框架方法之间不共享变量
    struts2 方法之间也是独立的,但其所有Action变量是共享的,当然这不影响程序的运行。
      

  9.   

    Thank you~
    我觉得反证这个问题,多实例并帮不上什么忙,Web Application里面的没一个用户的每一次请求,
    往往信息在Request对象里面,和Session对象里面,而不需要一个对象的某些成员变量的。
    所以,往往单实例就OK了。比如说用户A访问过某URL,某Servlet处理过,那么B用户也访问这个URL的时候,这个Servlet也要为其服务。
    那么A和B会不会修改某些对象?如果修改,就会改变某些对象(的状态),那么这就是有状态的了。
    如果你需要记录这种状态,那么一个Servlet对象当然不够了,要为A和B用户分别生成两个Servlet对象。
    但是Servlet的数量就增加了。这样做值得吗?而实际上JavaEE的规范是采用Session,其实就是PHP,ROR也是采用Session存储一些状态的,而不是Servlet。Session的结果是什么样的,其实用过就清楚了~
      

  10.   

    对于22楼的说法,虽然说的很多,但是我觉得没有根本性的讨论我的这个问题。。
    你说在view层面上的性能,我觉得是另外意义上的考虑,比如说。我个人在使用struts2的时候,基本不用他的标签。
    我习惯用el语言,习惯用velocity,对ognl语言整合el语言的不健全性,不完整性一直觉得不舒服。所以是被舍弃的。
    mvc本身是为了解耦,解除m和v的耦合。c层做的事情其实就是个request-response的过程。
    我这里不是为了对比springMVC和struts2那个更好,只是为了将这个action的单例问题拿出来讨论下。
    因为单例确实有优势,有劣势。
      

  11.   

    web服务中单例是为了节省资源吧,但是struts2里面的action所含的actionContext是每个用户对应一份(类似于session吧),用不了单例哇,设计问题吧,至于性能的优化那是框架里面的事了,不懂
      

  12.   

    框架设计需要考虑比较多,想来struts2没采用单例,但它解耦做得很好的。
      

  13.   

    楼上的都只是在说单例,还忽略了线程安全的问题。
    就拿struts1和struts2来说吧
    struts1中的action是单例的,也是线程不安全的,要使用全局变量,必须同步,否则会导致数据异常,因为他是一个实例对应多个请求
    struts2中的action是非单例的,是线程安全的,可以使用全局变量,不用同步的,因为它是一个实例对应一个请求的
    至于性能问题,要考虑到并发量来分析。
    用单例不一定节省资源的,要不然struts2就不会用非单例的了。
    在单例中,从第一个请求开始,该对象就会一直存在,除非web容器停止运行或者手动销毁。
    在非单例中,每一个请求对应一个实例,该请求响应完成,实例就会随时被销毁(与gc有关)
      

  14.   

    Struts2的Action从设计开始注定其不能是单例的,既然选择这种框架,就注定了会牺牲部分性能,它的优势就是解藕。如果你的系统对于性能的要求需要计较到这种程度,你肯定不会选择它。
      

  15.   

    struts1中的action是单例的,也是线程不安全的,要使用全局变量,必须同步,否则会导致数据异常,因为他是一个实例对应多个请求
    struts2中的action是非单例的,是线程安全的,可以使用全局变量,不用同步的,因为它是一个实例对应一个请求的35楼 这样说有点误导吧。请求正后再发。
    struts1 的action是单例,而且必须是线程安全的!
    struts2 的action是非单列,所以不用考虑线程安全问题!
      

  16.   

    单例只是节省了创建对象的时间,但是单实例对象不会被垃圾回收掉,常驻 JVM 内存。像 Servlet 这种生命周期很复杂的对象,对象的创建是很复杂的,因此其在 JVM 中是以单实例对象存在的,毕竟一个应用中不会有上万个 Servlet。而对于 Struts 2 的 Action 类来说,这个对象的创建基本上就是 new,相对于复杂的 Servlet 对象创建的时间来说可以忽略了。Struts 2 这么做的原因主要是与 Servlet API 解耦,Action 不再需要实现或者继承什么的。 
      

  17.   

    节省的还有内存~Servlet的生命周期并不复杂,Tomcat的简化版我都重写过,对于Servlet单实例来说,一直存在是应该的,应该直到server shutdown~
      

  18.   

    因为在同一个线程里,单例的action创建一遍就不new 了。struts2里每个请求都多一个new的步骤,性能自然会弱些
      

  19.   

    关于单例的问题,使用spring+Struts可以得到非常好的解决。
    所以现在SSH三个框架结合非常的好。
    这里是一个 S1和S2的比较的文章,可以看看他们之间的Action的区别。
    http://dev.firnow.com/course/3_program/java/javajs/200797/70140.html
      

  20.   

    单例模式是有线程安全隐患的,因为当多个进程访问的时候
    他们都会争用资源,就会产生线程安全问题。
    而像struts2的action,每个请求都会产生一个实例,也就是不会出现线程安全问题,他是线程安全的。
    呵呵,我理解的就这么多。
      

  21.   

    JAVA的垃圾回收机制 用软指针指向引用对象的地址,而不是直接指向对象
      

  22.   

    这个性能上可以忽略不计,而且在action上如果用单例的话会存在问题的,属性会出现混乱。
      

  23.   

    新的请求需要新的对象来处理。否则会出现错误
    spring的单例你指的是DI吗,比如dao,性能上确实会提高