如今主流的java的前端框架有:struts1,struts2,springmvc 還有最根本的servlet;前端
前些天一個朋友問我這方面的問題,就研究一番:java
1.關於struts1:spring
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就會實例化一個對象;這樣就不會有線程安全的問題了;mvc
哦,忘記了一種狀況,struts2+spring來管理注入的時候;若是把action設置爲單例模式,就會出現問題;能夠把action設置爲prototype類型,還有一個辦法是設置做用域(具體沒有實驗過)app
參考來源框架
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)使用只讀數據
參考文章: