SpringMVC成員變量並發狀態下使用測試


1.SpringMVC默認是單例的,使用成員變量在並發狀態下該成員變量的值是被共享的

測試平台   我們目前正在開發的電商項目  (架構組成SpringCloud + SpringBoot + Spring + SpringMVC + Mybatis)

 

測試說明  構造兩個並發訪問的請求,它們都會使用一個成員變量,其中一個請求會執行一段耗時15秒左右的for循環的代碼,另外一個請求不會執行這段代碼,但會修改成員變量的值

測試過程  第一個請求先訪問,在執行for循環時緊接着第二個請求訪問,第二個請求會馬上執行完並且改變成員變量的值,最后看前面這個請求執行完15秒的for循環后再使用這個成員變量時,值有沒有改變

 

測試源碼  

    

@RestController
@RequestMapping("/service")
public class SurvivalGoldReceiveController extends BaseController {


    private String nowDate = new SimpleDateFormat("yyyy-MM-dd HH:MM:ss").format(new Date());


    @RequestMapping(value = "/toSurvivalGoldReceive")
    public ModelAndView toSurvivalGoldReceive(){
        HttpServletRequest request = this.getRequest();
        GeCustomer geCustomer = (GeCustomer)request.getSession().getAttribute(UserPersonalConstant.LOGIN_USER);
        logger.info("start--nowDate = " + geCustomer.getCustomeraccount() + nowDate);
        logger.info("其它請求進來后");
        if ("youyuqi02".equals(geCustomer.getCustomeraccount())) {
            StringBuilder sb = new StringBuilder();
            long startTime = System.currentTimeMillis();
            for (int i = 0; i < 100000000; i++) {
                sb.append("測試SpringMVC中使用成員變量" + i);
                sb.append("測試SpringMVC中使用成員變量" + i);
                sb.append("測試SpringMVC中使用成員變量" + i);
                sb.append("測試SpringMVC中使用成員變量" + i);
                sb.append("測試SpringMVC中使用成員變量" + i);
                sb.delete(0,sb.length());
            }
            long estimatedTime = System.currentTimeMillis() - startTime;
            logger.info("執行一億次字符串的拼接與刪除耗時 : " + String.valueOf(estimatedTime).substring(0,2) + "秒");  //1s=1000毫秒=1000000微秒=1000000000納秒
        }else{
            nowDate = "成員變量被其它請求改變了";
        }
        logger.info("end--nowDate = " + geCustomer.getCustomeraccount() + nowDate);
        if(geCustomer == null){
            return go("/vipcenter/home");
        }else{
            return go("/vipcenter/survivalGoldReceive/survivalGoldReceiveList");
        }
    }
}

 

測試結果:第二個請求將成員變量nowDate的值改為了字符串“成員變量被其它請求改變了”,第一個請求再使用這個成員變量時,值已經發生了改變

 

總結:SpringMVC在單例情況下發生並發時會修改成員變量的值,所以慎用成員變量

 

 

2.設置controller為多例,@Scope("prototype")

測試源碼

@RestController
@Scope("prototype")
@RequestMapping("/service")
public class SurvivalGoldReceiveController extends BaseController {


    private String nowDate = new SimpleDateFormat("yyyy-MM-dd HH:MM:ss").format(new Date());


    @RequestMapping(value = "/toSurvivalGoldReceive")
    public ModelAndView toSurvivalGoldReceive(){
        HttpServletRequest request = this.getRequest();
        GeCustomer geCustomer = (GeCustomer)request.getSession().getAttribute(UserPersonalConstant.LOGIN_USER);
        logger.info("start--nowDate = " + geCustomer.getCustomeraccount() + nowDate);
        logger.info("其它請求進來后");
        if ("youyuqi02".equals(geCustomer.getCustomeraccount())) {
            StringBuilder sb = new StringBuilder();
            long startTime = System.currentTimeMillis();
            for (int i = 0; i < 100000000; i++) {
                sb.append("測試SpringMVC中使用成員變量" + i);
                sb.append("測試SpringMVC中使用成員變量" + i);
                sb.append("測試SpringMVC中使用成員變量" + i);
                sb.append("測試SpringMVC中使用成員變量" + i);
                sb.append("測試SpringMVC中使用成員變量" + i);
                sb.delete(0,sb.length());
            }
            long estimatedTime = System.currentTimeMillis() - startTime;
            logger.info("執行一億次字符串的拼接與刪除耗時 : " + String.valueOf(estimatedTime).substring(0,2) + "秒");  //1s=1000毫秒=1000000微秒=1000000000納秒
        }else{
            nowDate = "成員變量被其它請求改變了";
        }
        logger.info("end--nowDate = " + geCustomer.getCustomeraccount() + nowDate);
        if(geCustomer==null){
            return go("/vipcenter/home");
        }else{
            return go("/vipcenter/survivalGoldReceive/survivalGoldReceiveList");
        }
    }
}

 

測試結果  第一個請求最后獲取的成員變量的值並未改變

 

總結 第二種是多例的,每次訪問會創建一個Controller對象,屬於線程安全的,但會過多的耗費內存,第一種是單例的,只會創建一次對象,在並發情況下會修改成員變量的值,但會節省內存空間,所以,老司機都用第一種,但會有意識的避免使用成員變量。

 

參考文獻 springMVC 謹慎使用成員變量https://blog.csdn.net/panda_in5/article/details/78528762

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM