1. 程式人生 > >SpringMVC 併發訪問的執行緒安全性問題

SpringMVC 併發訪問的執行緒安全性問題

首先對於spring的IOC來說,物件是由Spring來幫我們管理,也就是在Spring啟動的時候,在Spring容器中,由Spring給我們建立的,Spring會幫我們維護,一般都是單例的,也就是一個物件。

spring生成物件預設是單例的。通過scope屬性可以更改為多例。

第一部分:驗證Spring生成物件預設是單例的。

下面我們來一個網上的例子驗證一下:

[html] view plain copy print?

  1. <bean id=”singleton” class=”java.util.Date” scope=”singleton”></bean>  
  2. <bean id=”prototype” class=”java.util.Date” scope=”prototype”></bean>  
[java] view plain copy print?

  1. package test;   
  2. import java.util.Date;  
  3. import org.springframework.context.ApplicationContext;  
  4. import org.springframework.context.support.ClassPathXmlApplicationContext;  
  5. import com.opensymphony.xwork2.ActionContext;  
  6. public class TestScope {  
  7.     public static void main(String[] args) {  
  8.        ApplicationContext context=new ClassPathXmlApplicationContext(”applicationContext-web.xml”);  
  9.        Date s1=(Date)context.getBean(“singleton”);  
  10.        Date p1=(Date)context.getBean(“prototype”);  
  11.        Date s2=(Date)context.getBean(“singleton”);  
  12.        Date p2=(Date)context.getBean(“prototype”);  
  13.        System.out.println(“單例:”+(s1==s2));  
  14.        System.out.println(“非單例:”+(p1==p2));  
  15.     }  
  16. }  


輸出結果:

結果

單例:true

非單例:false

注:複合資料型別的“== ”對比的是記憶體中存放的地址,所以此處我們採用“==”去對比

因為object中的equals初始行為是比較記憶體中的地址,但在一些類庫中被覆蓋掉了如(StringIntegerDate等)

第二部分:SpringMVC和Struts2中是併發訪問否會存線上程安全問題。

對於使用過SpringMVC和Struts2的人來說,大家都知道SpringMVC是基於方法的攔截,而Struts2是基於類的攔截。

對於Struts2來說,因為每次處理一個請求,struts就會例項化一個物件;這樣就不會有執行緒安全的問題了;

而Spring的controller預設是Singleton的,這意味著每一個request過來,系統都會用原有的instance去處理,這樣導致兩個結果:

一是我們不用每次建立Controller,二是減少了物件建立和垃圾收集的時間;由於只有一個Controller的instance,當多個執行緒呼叫它的時候,它裡面的instance變數就不是執行緒安全的了,會發生竄資料的問題。

當然大多數情況下,我們根本不需要考慮執行緒安全的問題,比如dao,service等,除非在bean中聲明瞭例項變數。因此,我們在使用spring mvc 的contrller時,應避免在controller中定義例項變數。 
如:

[java] view plain copy print?

  1. public class Controller extends AbstractCommandController {    
  2.     protected Company company;  
  3.     protected ModelAndView handle(HttpServletRequest request,HttpServletResponse response,Object command,BindException errors) throws Exception {  
  4.         company = …………….;           
  5.      }             
  6.  }    


解決方案:

有幾種解決方法:
1、在Controller中使用ThreadLocal變數
2、在spring配置檔案Controller中宣告 scope=”prototype”,每次都建立新的controller
所在在使用spring開發web 時要注意,預設Controller、Dao、Service都是單例的。

例如:

[java] view plain copy print?

  1. @Controller  
  2. @RequestMapping(”/fui”)  
  3. public class FuiController extends SpringController {  
  4. //這麼定義的話就是單例  
  5. @Controller  
  6. @Scope(”prototype”)  
  7. @RequestMapping(”/fui”)  
  8. public class FuiController extends SpringController {  
  9. //每次都建立  

第三部分:springMVC與struts2的區別。

下面是從網路上摘抄的一段對比,大家可以看看

1. 機制:spring mvc的入口是servlet,而struts2是filter,這樣就導致了二者的機制不同。

2. 效能:spring會稍微比struts快。spring mvc是基於方法的設計,而sturts是基於類,每次發一次請求都會例項一個action,每個action都會被注入屬性,而spring基於方法,粒度更細,但要小心把握像在servlet控制資料一樣。spring3 mvc是方法級別的攔截,攔截到方法後根據引數上的註解,把request資料注入進去,在spring3 mvc中,一個方法對應一個request上下文。而struts2框架是類級別的攔截,每次來了請求就建立一個Action,然後呼叫setter getter方法把request中的資料注入;struts2實際上是通過setter getter方法與request打交道的;struts2中,一個Action物件對應一個request上下文。

3. 引數傳遞:struts是在接受引數的時候,可以用屬性來接受引數,這就說明引數是讓多個方法共享的。

4. 設計思想上:struts更加符合oop的程式設計思想, spring就比較謹慎,在servlet上擴充套件。

5. intercepter的實現機制:struts有以自己的interceptor機制,spring mvc用的是獨立的AOP方式。這樣導致struts的配置檔案量還是比spring mvc大,雖然struts的配置能繼承,所以我覺得論使用上來講,spring mvc使用更加簡潔,開發效率Spring MVC確實比struts2高。spring mvc是方法級別的攔截,一個方法對應一個request上下文,而方法同時又跟一個url對應,所以說從架構本身上spring3 mvc就容易實現restful url。struts2是類級別的攔截,一個類對應一個request上下文;實現restful url要費勁,因為struts2 action的一個方法可以對應一個url;而其類屬性卻被所有方法共享,這也就無法用註解或其他方式標識其所屬方法了。spring3 mvc的方法之間基本上獨立的,獨享request response資料,請求資料通過引數獲取,處理結果通過ModelMap交回給框架方法之間不共享變數,而struts2搞的就比較亂,雖然方法之間也是獨立的,但其所有Action變數是共享的,這不會影響程式執行,卻給我們編碼,讀程式時帶來麻煩。

6. 另外,spring3 mvc的驗證也是一個亮點,支援JSR303,處理ajax的請求更是方便,只需一個註解@ResponseBody ,然後直接返回響應文字即可。

總結:

這樣也說明了SpringMVC還有Servlet都是方法的執行緒安全,所以在類方法宣告的私有或者公有變數不是執行緒安全的,而struts2的確實是執行緒安全的。

第四部分:那麼對於Struts2+Spring來管理注入的時候呢?

Struts2它是多例項的,對於每個請求都會生成1個例項,spring預設是單例項的(下面針對Struts與Spring整合的兩種方式分別來介紹struts2和spring的兩種整合方式

一:對於無Spring外掛(Struts2-spring-plugin-XXX.jar)的整合方式,需要在spring的action Bean中加業務邏輯控制器類配scope=”prototype”。

[java] view plain copy print?

  1. <bean id=“user” class=”modle.User” scope=”prototype”></bean>  

:對於有Spring外掛(Struts2-spring-plugin-XXX.jar)的整合方式:反編譯StrutsSpringObjectFactory以及相關的程式碼才發現,如果在struts action的配置檔案中<action name=”..” class=”..”/>中class寫的如果是完整的包名和類名的話就是struts建立action物件,也就是多例項的;

總結:如果是spring配置檔案中的 bean的名字的話就是spring建立,那麼單例項還是多例項就由spring的action Bean中的業務邏輯控制器類是否配置為scope=”prototype”,有就是多例項的,沒有就是單例項的,順序是先從spring中找,找不到再從struts配置檔案中找。

相關推薦

淺談Semaphore類 如何控制某個方法允許併發訪問執行的個數?

Semaphore類有兩個重要方法 1、semaphore.acquire(); 請求一個訊號量,這時候訊號量個數-1,當減少到0的時候,下一次acquire不會再執行,只有當執行一個release()的時候,訊號量不為0的時候才可以繼續執行acquire 2、semaphore.release();

Java併發基礎—執行安全性

執行緒安全性         當多個執行緒訪問某個類時,不管執行時環境採用何種排程方式或者這些程序如何交替執行,並且在主調程式碼中無需任何額外的同步或協同,這個類都能表現出正確的行為,那麼就稱這個類是執行緒安全的。 執行緒安全性——原子性         提供了互斥訪問

Java併發程式設計(8)-使用閉鎖測試併發執行安全性

本文將介紹什麼是閉鎖,在java中的閉鎖實現:CountDownLatch類及其常用方法等,最後給出了一個使用閉鎖模擬執行緒併發的demo,用以簡單地測試任務是否為執行緒安全。 一、什麼是閉鎖 閉鎖(Latch)是在併發程式設計中常被提及的概念。閉鎖是一

Guava併發:RateLimiter限制資源的併發訪問執行

RateLimiter類似於JDK的訊號量Semphore,他用來限制對資源併發訪問的執行緒數。 RateLimiter limiter = RateLimiter.create(4.0); //每秒不超過4個任務被提交 limiter.acquire();  //請求Ra

SpringMVC 併發訪問執行安全性問題

首先對於spring的IOC來說,物件是由Spring來幫我們管理,也就是在Spring啟動的時候,在Spring容器中,由Spring給我們建立的,Spring會幫我們維護,一般都是單例的,也就是一個物件。 spring生成物件預設是單例的。通過scope屬性可以更改為多例。 第一部分:驗證Spring

Spring併發訪問執行安全性問題總結

好像是在去年畢業面試的時候,面試官問了我這個問題,如何保證Spring併發訪問的執行緒安全問題,當時的我也只是對這些有所瞭解,僅僅知道spring中的controller、serivce、dao預設為單例,只要不在這些單例中使用成員變數就可以了,然後工作至今,我還是對其中原理

Spring併發訪問執行安全性問題(高度總結)

spring中的併發訪問題: 我們知道在一般情況下,只有無狀態的Bean才可以在多執行緒環境下共享,在Spring中,絕大部分Bean都可以宣告為singleton作用域。 那麼對於有狀態的bean呢?Spring對一些(如RequestContextHolder、Tra

Spring 是如何解決併發訪問執行安全性問題的

        springmvc的controller是singleton的(非執行緒安全的),這也許就是他和struts2的區別吧!和Struts一樣,Spring的Controller預設是Singleton的,這意味著每個request過來,系統都會用原有的inst

Spring併發訪問執行安全性問題

springmvc的controller是singleton的(非執行緒安全的),這也許就是他和struts2的區別吧和Struts一樣,Spring的Controller預設是Singleton的,這意味著每個request過來,系統都會用原有的instance去處理,這

Java併發理論基礎—執行安全性

執行緒安全性         當多個執行緒訪問某個類時,不管執行時環境採用何種排程方式或者這些程序如何交替執行,並且在主調程式碼中無需任何額外的同步或協同,這個類都能表現出正確的行為,那麼就稱這個類是執行緒安全的。 執行緒安全性——原子性 &nbs

併發程式設計從入門到放棄1--執行安全性

什麼是執行緒安全性?        當多個執行緒訪問某個類時,不管執行時環境採用何種排程方式或者這些程序將如何交替執行,並且在主調程式碼中不需要任何額外的同步或協同,這個類都能表現出正確的行為,那麼就稱這個類是執行緒安全的。 執行緒安全性包括原子性,可見性

Java併發程式設計(9)-使用閉鎖測試併發執行安全性

文章目錄 一、什麼是閉鎖 二、CountDownLatch類介紹 2.1、什麼是CountDownLatch 2.2、構造方法 2.3、主要方法 三、使用閉鎖完成併

併發程式設計實戰(1):執行安全性之有狀態和無狀態物件

程序和執行緒的區別 程序是具有一定獨立功能的程式關於某個資料集合上的一次執行活動,程序是系統進行資源分配和排程的一個獨立單位. 執行緒是程序的一個實體,是CPU排程和分派的基本單位,它是比程序更小的能獨立執行的基本單位. 程序在執行過程中擁有獨立的記憶體單元,程序

《java併發程式設計實戰》之 執行安全性

1.執行緒安全性 當多個執行緒訪問某個類時,不管執行時環境採用何種排程方式或者這些執行緒將如何交替執行,並且在主調程式碼中不需要任何額外的同步或協同,這個類都能表現出正確的行為,那麼這個類就是執行緒安全的。 無狀態物件一定是執行緒安全的,何為無狀態,就是類中不包含任何域,也不包含各種其

[讀書筆記][Java併發程式設計實戰]第二章 執行安全性

                                          第二章 執行緒安全性 1-什麼是執行緒安全的類? 當多個執行緒訪問某一個類時,不管執行時環境採用何種排程方式或者這些執行緒將如何交替執行,並且在主調程式碼中不需要任何額外的同步或協同,這個

併發實戰 之「 執行安全性

溫馨提示:本系列博文(含示例程式碼)已經同步到 GitHub,地址為「java-skills」,歡迎感興趣的童鞋Star、Fork,糾錯。 在早期的計算機中不包含作業系統,它們從頭到尾只能執行一個程式,並且這個程式能訪問計算機中的所有資源。在這種環境中,不僅

《Java併發程式設計實戰》—— 第二章 執行安全性

編寫執行緒安全的程式碼,核心在於要對狀態訪問操作進行管理,特別是對共享的和可變的狀態的訪問。 物件的狀態 同步機制: synchronized(獨佔的加鎖方式) volatile 顯式鎖 原子變數 多個執行緒訪問同一個變數時,有3種方式保障安全

《JAVA併發程式設計實踐》第二章 執行安全性

1.多執行緒環境為什麼會出現問題? 由於競態條件的存在。 競態條件:基於一種可能失效的觀察結果來做出判斷或執行某個計算 競態條件分兩種: - **先檢查後執行**

Java併發(理論知識)—— 執行安全性

1、什麼是執行緒安全性                                         &nb

java併發程式設計實戰:執行安全性筆記

執行緒安全性 可以在多個執行緒中呼叫,並且線上程之間不會出現錯誤的互動。 原子性 原子性:即一個操作或者多個操作 要麼全部執行並且執行的過程不會被任何因素打斷,要麼就都不執行。 i++ 和 ++i就不是原子性。 ++i 讀取值,將值加1,將值寫入i.”讀取,修改,寫入