+ U4 b& @; k3 H; ? l. y. r: ?- V1、Struts19 S& ^% x- T2 V2 Y" y
Struts1是单例模式,也就是所,Web容器(例如:Tomcat)启动的时候,就会实例化一个Action对象,那么所有请求都是用的这个对象。所以当遇到2个请求并发的时候,那么其实他们调用的是同一个类,这个时候当你在Action内部定义属性的时候,就会产生线程同步的问题。/ p2 }+ ~. C4 ^+ ~" k4 R
例如: 6 N1 e: G c1 n你在Action定义了一个 int i = 0; 4 O2 D0 I. g* I4 u) C. B2 B9 _然后在这个Action里面的某一个方法里面对这个i进行操作。当并发的时候就会遇到问题。 8 K, ~- z- j/ y2 U: I所以:我们在用struts1的时候不能在action里面定义属性。要用到只的话只能在方法里面定义。, J' H. z' g1 C! q$ T0 [
2、struts2$ S* I3 Q5 k: b, g4 d. I
Struts 2 Action对象为每一个请求产生一个实例,因此没有线程安全问题。所以我们可以在Struts2的Action里面去定义属性。但是Struts2由于 Action和普通的java类没有任何区别(也就是不用像Struts1里面那样去实现一个Struts的接口,有兴趣的朋友可以自己去了解),所以我们可以用Spring去管理Struts2的Action,这个时候我们就要注意了,因为当我们在spring里面去定义bean的时候,spring默认用的是单例模式。所以在这个时候,你就要修改Spring的配置文件---即修改scope为prototype。 # ~, ?+ ]- e0 G) h为什么struts1中并没有考虑到线程问题,因为所有的代码都是写在execute的方法中,所有变量都是定义在里面,所以没有线程安全问题。 * A/ X) X. [" Q2 `8 g* {而现在的struts2就不一样了。struts2的action中就像一个POJO一样,定义了很多的类变量。这就有线程安全问题了。。此时,就使用scope=prototype来指定是个原型模式,而不是单例,这样就解决了线程安全问题。每个线程都是一个新的实例。。; r, } d( r- p# B
4 T8 D2 O/ Y, G. V/ d但是,线程同步是不得以的方法,是比较复杂的,而且会带来性能的损失。等效的代码中,不需要同步在编写容易度和性能上会更好些。 5 t' P0 l9 ^2 n9 p7 \我这里强调的是什么代码是始终为线程安全的、是不需要同步的。如下:* ^5 K( H% w9 |- B, `; @8 K1 F3 N
1)常量始终是线程安全的,因为只存在读操作。 0 r; P$ t% F+ C4 s2)对构造器的访问(new 操作)是线程安全的,因为每次都新建一个实例,不会访问共享的资源。( _- R$ }- G7 N' v$ |
3)最重要的是:局部变量是线程安全的。因为每执行一个方法,都会在独立的空间创建局部变量,它不是共享的资源。局部变量包括方法的参数变量。: l c7 l* j7 z7 C
struts user guide里有: 1 M8 f, e7 u, VOnly Use Local Variables - The most important principle that aids in thread-safe coding is to use only local variables, not instance variables , in your Action class. * c3 R0 i! a. p @' a! F译:只使用用局部变量。--编写线程安全的代码最重要的原则就是,在Action类中只使用局部变量,不使用实例变量。 7 W9 b2 x, q3 `; j& v) F o& K; ~8 a6 ?2 ^+ K) A