java吧 关注:1,298,357贴子:12,837,111
  • 12回复贴,共1

终于跑通源码解析Struts1和Struts2里面的Action线程安全

只看楼主收藏回复

经过我的不懈努力。终于跑完了Struts1跟Struts的源码了。
也终于知道为什么说Action的线程安全问题了。


1楼2013-01-21 22:40回复
    是不是用了threadLocal模式


    来自Android客户端3楼2013-01-22 00:47
    回复
      2026-02-28 10:16:58
      广告
      不感兴趣
      开通SVIP免广告
      Struts1里面典型的Action创建方法,大家可以看到是先去map里面寻找,找到就直接返回,找不到就创建一个放入map中(即actions),这里注意的是去map里面寻找的时候,加了synchronized 关键字,防止多线程访问的时候出问题.
      看到这里,大家又一次清楚了所有的同类请求,用的是同一个Antion实例,那么如果在这个Action里面定义了字段变量,那么线程就是不安全的了,为什么了,因为后面的请求如果改了这个字段,那么就把前面的请求的字段覆盖掉了,举个非常简单的例子,看下面的代码


      4楼2013-01-22 10:00
      回复

        public class UserAction extends Action {
        private User user;
        ......


        5楼2013-01-22 10:01
        回复
          如果每次用户登录的后把当前用户都保存在上面的user对象里面,假如有两个请求访问当前UserAction,第一个请求把user置为A,第二个请求访问的时候把user置为B,那么第一个用户里面保存的A对象就被第二个请求的B对象覆盖了,这里就产生了多线程访问的数据混乱问题,也就是线程的不安全.
          所以在Struts1的Action里面如果不定义字段变量,这个Action就是安全的,反之不安全,当然定义局部变量是没有问题.


          6楼2013-01-22 10:01
          回复
            Struts2中Action的创建
            还是先贴出在Struts2里面创建Action的地方:
            protected void createAction(Map<String, Object> contextMap) {
            // load action
            String timerKey = "actionCreate: " + proxy.getActionName();
            try {
            UtilTimerStack.push(timerKey);
            action = objectFactory.buildAction(proxy.getActionName(), proxy.getNamespace(), proxy.getConfig(), contextMap);
            大家可以看到这个action是由objectFactory来创建的,那么我们继续跟踪,进入上面的buildAction看看怎么写的:如下
            public Object buildAction(String actionName, String namespace, ActionConfig config, Map<String, Object> extraContext) throws Exception {
            return buildBean(config.getClassName(), extraContext);
            }
            可以看出来他是调用了buildBean方法,没关系,我们继续跟踪buildBean方法,如下
            public Object buildAction(String actionName, String namespace, ActionConfig config, Map<String, Object> extraContext) throws Exception {
            return buildBean(config.getClassName(), extraContext);
            }


            7楼2013-01-22 10:04
            回复
              上面是两个适配的方法可以不管,继续看这里面掉了两个参数的buildBean,那么再看看两个参数的buildBean做了什么事情
              public Object buildBean(Class clazz, Map<String, Object> extraContext) throws Exception {
              return clazz.newInstance();
              }
              看到这里大家估计都恍然大悟了,原来每次用户的请求都调用了newInstance方法生成了一个新的Action对象,这样的话就不存在每个线程安全不安全的问题了,两个线程没有交集,那么肯定是线程安全的了 .
              注:这里只是看了Struts2自己产生Action对象的说明,如果你的Struts2和Spring有整合,那么要在Spring的Action的作用域要设置在prototype才行,这样就保证每次都是产生新的Action.


              8楼2013-01-22 10:05
              回复


                9楼2013-01-22 10:08
                回复
                  2026-02-28 10:10:58
                  广告
                  不感兴趣
                  开通SVIP免广告


                  通过百度相册上传10楼2013-01-22 10:19
                  回复



                    IP属地:广西12楼2014-04-21 13:26
                    回复
                      到底谁是线程安全呢?struts1安全,还是struts2安全。。


                      13楼2014-05-12 11:10
                      收起回复