Struts2的action是否为线程安全?Struts1的区别?

昨天有人问到struts2是不是线程安全的?是不是单例的?跟struts1有什么区别 他是怎么实现的?我就一下子懵缺了,strtus2肯定是线程安全的,因为从没有发现数据不安全的问题,因此肯定不是单例  但是具体是怎么实现的就不得而知了,更不清楚Struts1的区别,因此准备查一下并记录下来

首先我们要明白strtus中的action请求其实就servlet,那么servlet有什么特性?是不是线程安全的呢?

servlet的生命周期?

服务器只创建每个servlet的单一实例,首次创建servlet时,它的init方法会被调用,因此,init是放置一次性设置代码的地方,之后,针对每个用户的请求都会创建一个线程,该线程调用前面创建的实例方法。多个并发请求一般会导致多个线程同时调用service(线程安全),service方法会依据接受到HTTP请求的类型,调用doXXX方法。最后如果服务器卸载某个servlet就会调用servlet的destroy方法。

由于servlet是单例的,因此当多个线程请求时就会造成数据风险,但也并不是不可避免的风险,解决方法:

 1.注意全局变量的使用、注意共有数据的访问

 2.单线程访问servlet,继承singleThreadModel,这样就避免的全局变量数据的使用问题,但是该方法不提倡使用,数据并发访问会造成阻塞等待

Public class Servlet1 extends HttpServlet implements SingleThreadModel{

……..

}

 3.添加方法同步锁Synchronized,但是该方法也不提倡,原因与2相同


Struts1的特性:

       当第一次*.do请求过来时,在内存中的actionmapping中找到相对应的action,然后new出这个action放在缓存中,当第二次一样的请求过来时,还是找这个action,所以对于struts1来说,action是单实例的,只有一个,理论上来讲action就不是线程安全的了,但是在用Struts 1开发时并没有考虑到线程安全问题,这是因为我们在Action中使用的基本都是局部变量,而“局部变量是线程安全的。因为每执行一个方法,都会在独立的空间创建局部变量,它不是共享的资源。局部变量包括方法的参数变量”。在Struts 1中,所有的变量都是定义在Action中我们要执行的方法里的(Action中的execute方法或DispatchAction中指定要执行的方法),我们用于封装客户端请求参数的ActionForm,也是作为一个参数传入,也属于局部变量,因此,不存在线程安全问题。跟servlet相同并不是不可以使用共有变量,我们可以加锁达到同步,只是在性能上就要折衷了。

 

Struts2的特性:

      Struts 2 的 Action 对象为每一个请求产生一个实例,因此,虽然在Action中定义了很多全局变量,也不存在线程安全问题。Struts 2框架在处理每一个用户请求的时候,都建立一个单独的线程进行处理,值栈ValueStack也是伴随着局部线程而存在的。在该线程存在过程中,可以随意访问值栈,这就保证了值栈的安全性。在Struts 2中,ActionContext是一个局部线程,这就意味着每个线程中的ActionContext内容都是唯一的。所以开发者不用担心Action的线程安全。

    在Spring的Bean配置中,存在这样两种情况:


  1. <bean id="testManager" class="com.sw.TestManagerImpl" scope="singleton" />  
  2.   
  3.  <bean id="testManager" class="com.sw.TestManagerImpl" scope="prototype" /> 

当然,scope的值不止这两种,还包括了request,session 等。但用的最多的还是singleton单态,prototype多态。

singleton表示该bean全局只有一个实例,Spring中bean的scope默认也是singleton.

prototype表示该bean在每次被注入的时候,都要重新创建一个实例,这种情况适用于有状态的Bean.


转载scope默认信息:http://blog.sina.com.cn/s/blog_5f12739d0100cre0.html

    scope="prototype">
  
 

 


 scope="prototype"没写的问题,项目中对一个表的增删该操作是用一个action,这个action有add,update,delete,save这些方法,
 添加和修改是共用一个页面,当页面得到id时代表进行的修改操作,反之是添加操作。因为在配置spring的bean是忘了写scope="prototype"
 所以每次添加时都显示最后一次访问过的记录,scope="prototype"会在该类型的对象被请求
 时创建一个新的action对象。如果没有配置scope=prototype则添加的时候不会新建一个action,他任然会保留上次访问的过记录的信息
webwork的Action不是线程安全的,要求在多线程环境下必须是一个线程对应一个独立的实例,不能使用singleton。所以,我们在Spring配置WebworkAction Bean时,需要加上属性scope=”prototype”或singleton=”false”。
singleton模式指的是对某个对象的完全共享,包括代码空间和数据空间,说白了,如果一个类是singleton的,假如这个类有成员变量,那么这个成员变量的值是各个线程共享的(有点类似于static的样子了),当线程A往给变量赋了一个值以后,线程B就能读出这个值。因此,对于前台Action,肯定不能使用singleton的模式,必须是一个线程请求对应一个独立的实例。推而广之,只要是带数据成员变量的类,为了防止多个线程混用数据,就不能使用singleton。对于我们用到的Service、Dao,之所以用了singleton,就是因为他们没有用到数据成员变量,如果谁的Service需要数据成员变量,请设置singleton=false。



 





你可能感兴趣的:(面试,Struts,Spring)