springmvc的control 的线程是否安全的问题

关于java Servlet,Struts,springMVC 的线程安全问题

现在主流的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)使用只读数据

猜你喜欢

转载自weitao1026.iteye.com/blog/2294182