`
m635674608
  • 浏览: 5028264 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

Servlet,Struts,springMVC 的线程安全问题

    博客分类:
  • java
 
阅读更多

现在主流的java的前端框架有:struts1,struts2,springmvc 还有最根本的servlet;

前些天一个朋友问我这方面的问题,就研究一番:

1.关于struts1:

Struts1使用的ActionServlet是单例的,由这一个servlet处理所有.do请求。RequestProcessor也是单例。

RequestProcessor的processActionCreate方法:

/**
  * <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);
 }

从结果可以知道,是单例,既然是单例,如果当使用实例变量的时候就会有线程安全的问题;

2.关于struts2

我们知道我们使用struts2的时候,都是使用actionContext ;都是使用里面的实例变量,让struts2自动匹配成对象的。如果不是线程安全那全完了;所以struts2必须是线程安全的;因为每次处理一个请求,struts就会实例化一个对象;这样就不会有线程安全的问题了;

哦,忘记了一种情况,struts2+spring来管理注入的时候;如果把action设置为单例模式,就会出现问题;可以把action设置为prototype类型,还有一个办法是设置作用域(具体没有实验过)

参考来源

 

3.关于SpringMVC

SpringMVC的controller默认是单例模式的,所以也会有多线程并发的问题;

参考代码:

@RequestMapping("/user")
@Controller
Class UserController
{
    @Resource
    UserService userService;

    @RequestMapping("/add")
    public void testA(User user){
        userService.add(user);
    }

    @RequestMapping("/get")
    public void testA(int id){
        userService.get(id);
    }
}

@Service("userService")
Class UserService{

    public static Map<Integer,User> usersCache = new HashMap<String,User>();

    public void add(User user){
        usersCache.put(user.getId(),user);
    }

    public void get(int id){
        usersCache.get(id);
    }

}

usersCache就是非线程安全的。

解决方法:

1)同步共享数据

2)不使用成员实例变量;

3)使用只读数据

分享到:
评论

相关推荐

    springmvc+mybatis面试题

    SpringMVC的控制器默认是单例模式,因此在多线程环境下可能存在线程安全问题。为避免这个问题,控制器不应包含可变状态,即避免在控制器中定义实例变量。如果必须存储数据,可以使用Session或者ThreadLocal,但需...

    Java面试题线程部分.docx

    对于Web开发中的线程安全问题,servlet、struts和springMVC的线程模型有所不同。servlet和springMVC使用单例模式,即一个应用只有一个Servlet实例,因此可能出现线程安全问题。相反,struts使用多实例模式,每个请求...

    简单了解SpringMVC与Struts2的区别

    此外,Struts2需要针对每个request进行封装,把request,session等servlet生命周期的变量封装成一个一个Map,供给每个Action使用,并保证线程安全,这也使得Struts2比较耗费内存。 在拦截器实现机制上,Struts2有以...

    SpringMVC面试专题及答案.pdf

    - **线程安全问题**:由于多个线程可能同时访问同一实例,因此可能会导致线程安全问题。 - **解决方案**:为了避免线程安全问题,通常的做法是在 Controller 中避免使用实例变量,转而使用局部变量或依赖注入的方式...

    SpringMVC面试专题1

    SpringMVC的控制器默认是单例模式,多线程环境下可能导致线程安全问题。解决方案是避免在控制器中定义实例变量,或者使用ThreadLocal来确保线程局部变量的安全。 6. **SpringMVC与Struts2的区别** - 入口不同:...

    SpringMVC的相关问题.docx

    - Spring MVC的控制器默认是单例模式,因此在多线程环境下可能存在线程安全问题。解决方案是避免在控制器中定义实例变量,而是使用服务层对象来处理业务逻辑。 5. **Spring MVC与Struts2的区别** - 入口不同:...

    SpringMVC面试专题.pdf

    关于线程安全问题,SpringMVC的控制器默认是单例模式的,这在多线程环境下可能会导致线程安全问题。为了解决这个问题,在控制器里面不能写字段。这是因为字段可能会被多个线程共享,从而导致状态冲突。 在SpringMVC...

    23道SpringMVC常见面试题.docx

    - SpringMVC 控制器默认是单例模式,多线程环境下需注意线程安全问题。 - 可以通过 @RequestMapping 注解进行请求映射,配合 method 属性限制请求类型。 - 参数获取直接通过形参声明,SpringMVC 会自动注入 Request...

    SpringMVC面试题

    SpringMvc的控制器是单例模式的,因此在多线程访问的时候会有线程安全问题,可以通过不在控制器里面写字段来解决。 SpringMvc和Struts2的区别是:SpringMvc的入口是一个servlet,即前端控制器,而Struts2入口是一...

    SpringMVC入门精通

    - **Struts2**:为了保证线程安全,需要为每个请求创建新的 Action 实例,因此在内存占用方面可能会更高。 4. **配置复杂度**: - **Struts2**:拥有自己的拦截器机制,配置相对复杂。 - **SpringMVC**:利用 ...

    SpringMVC22问面试真题+答案1

    - 控制器默认为单例模式,在多线程环境下可能存在线程安全问题。为避免这种情况,控制器不应持有状态,即不应有实例变量。 6. **SpringMVC 与 Struts2 的区别**: - 入口点不同:SpringMVC 通过 Servlet,Struts2...

Global site tag (gtag.js) - Google Analytics