Struts1,Struts2,springmvc,servlet线程安全问题

字数 484阅读 118

Struts1线程不安全

/**
  * <p>Return an <code>Action</code> instance that will be used to process
  * the current request, creating a new one if necessary.</p>
  *
  * @param request  The servlet request we are processing
  * @param response The servlet response we are creating
  * @param mapping  The mapping we are using
  * @return An <code>Action</code> instance that will be used to process
  *         the current request.
  * @throws IOException if an input/output error occurs
  */
 protected Action processActionCreate(HttpServletRequest request,
     HttpServletResponse response, ActionMapping mapping)
     throws IOException {
     // Acquire the Action instance we will be using (if there is one)
     String className = mapping.getType();
     if (log.isDebugEnabled()) {
         log.debug(" Looking for Action instance for class " + className);
     }
     Action instance;
     // 这个同步快保证了Action的单例
     synchronized (actions) {
         // Return any existing Action instance of this class
         instance = (Action) actions.get(className);
         if (instance != null) {
             if (log.isTraceEnabled()) {
                 log.trace("  Returning existing Action instance");
             }
             return (instance);
         }
         // Create and return a new Action instance
         if (log.isTraceEnabled()) {
             log.trace("  Creating new Action instance");
         }
         try {
             instance = (Action) RequestUtils.applicationInstance(className);
             // Maybe we should propagate this exception
             // instead of returning null.
         } catch (Exception e) {
             log.error(getInternal().getMessage("actionCreate",
                     mapping.getPath()), e);
             response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
                 getInternal().getMessage("actionCreate", mapping.getPath()));
             return (null);
         }
         actions.put(className, instance);
         if (instance.getServlet() == null) {
             instance.setServlet(this.servlet);
         }
     }
     return (instance);
 }

在一个应用的生命周期中,Struts框架只会为每个Action类创建一个Action实例(与servlet是一样的)。所有的客户请求共享一个Action实例,并且所有请求线程可以同时执行它的execute()方法。
所以,每个action只有一个实例, 在action打印this也可以看到, 确实是一样的,
所以,
不要在Action里面使用全局变量记忆数据, 没有意义而且不安全

Struts2线程安全

因为每次处理一个请求,struts就会实例化一个对象

如果在spring注入action时使用了单例,也会导致线程不安全

对于使用过SpringMVC和Struts2的人来说,大家都知道SpringMVC是基于方法的拦截,而Struts2是基于类的拦截。

对于Struts2来说,因为每次处理一个请求,struts就会实例化一个对象;这样就不会有线程安全的问题了;
而Spring的controller默认是Singleton的,这意味着每一个request过来,系统都会用原有的instance去处理,这样导致两个结果:
一是我们不用每次创建Controller,二是减少了对象创建和垃圾收集的时间;由于只有一个Controller的instance,当多个线程调用它的时候,它里面的instance变量就不是线程安全的了,会发生窜数据的问题。

servlet和springmvc都是线程不安全

<b>如果要让struts1,springmvc,servlet都变成线程安全该怎么做<b/>
1.与Spring集成@Scope("prototype"),对应每次请求产生一个新的action实例。
2.加锁

当然这些讨论都针对实例变量,如果action中共享的是静态变量,单例不单例都线程不安全了。

推荐阅读更多精彩内容