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

最新文章

  1. shell 条件判断
  2. poj 3734 Blocks
  3. Spring-事物配置
  4. Visual Studio原生开发的10个调试技巧(二)
  5. SQLServer 之 2008还原的时候无法获得对数据库的独占访问权解决
  6. moveToThread的最简单用法(依葫芦画瓢即可)(使得线程也更偏向于信号槽的使用方法)
  7. 好看的Select下拉框是如何制造的
  8. Codeforces Round #246 (Div. 2) D. Prefixes and Suffixes(后缀数组orKMP)
  9. eclipse下配置安装ssm图文教程(web版)
  10. Dom 简介
  11. java-多个数的和
  12. 【转自Testerhome】iOS 真机如何安装 WebDriverAgent
  13. React .js框架的环境搭建
  14. springboot中访问jsp文件方式
  15. vmware彻底隐藏控制栏白条
  16. js实现全选/全不选、反选
  17. Process多进程的创建方法
  18. I2C总线的仲裁机制
  19. OpenCV开发环境搭建-并测试一个图像灰度处理程序
  20. 淘宝用户api 如何获得App Key和API Secret

热门文章

  1. js初级练习
  2. Oracle数据库自带表或者视图
  3. python 查找日志关键字
  4. zt (stack overflow 介绍)
  5. Nuxt 自动化部署及打包后文件自动上传七牛云
  6. 004-CSS怎样让背景充满整个屏幕
  7. hibernate一级缓存及对象的状态
  8. oracle之在java中调用
  9. 轻量级集群管理软件-Ansible
  10. GDI和内核对象区别