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
SpringMVC成员变量并发状态下使用测试的更多相关文章
- php高并发状态下文件的读写
php高并发状态下文件的读写 背景 1.对于PV不高或者说并发数不是很大的应用,不用考虑这些,一般的文件操作方法完全没有问题 2.如果并发高,在我们对文件进行读写操作时,很有可能多个进程对进一文件 ...
- 读/写锁的实现和应用(高并发状态下的map实现)
程序中涉及到对一些共享资源的读和写操作,且写操作没有读操作那么频繁.在没有写操作的时候,两个线程同时读一个资源没有任何问题,所以应该允许多个线程能在同时读取共享资源.但是如果有一个线程想去写这些共享资 ...
- binlog在并发状态下的记录
前两天看binlog发现个奇怪的地方:对于position靠后的记录,timestamp却比之前的记录还要小.当时觉得大概和并发有关系 后来做了个实验 开两个session 对于session1: b ...
- C语言中 struct成员变量顺序对内存的占用
在C语言的结构体中,是会按照其变量类型来进行分配内存大小的.但是对于不同的编译器,结果是不同的,在VC++6.0中是怎么个分配情况呢?用一下C中的关键字sizeof()来测试下,注意sizeof()不 ...
- java在继承中父类的成员变量是否会被子类所覆盖
假如 父类 int num =7:子类 int num =9:父类是否会被子类所覆盖? 给你看两个例子: 第一个例子: 第二个例子: 这两个例子的区别只有一句话 由此证明了子类从父类继承的时候 ...
- 访问权限系列一(public/private/protected/default):成员变量
通过两个程序包对自身或互相之间的访问,得到结果.(先编译Test_01,得到class文件,通过Test的集中访问情况) 如下Test.java中内容: package com.java; /* * ...
- python中的类的成员变量以及property函数
1 python类的各种变量 1.1 全局变量 在类外定义的变量. 1.2 类变量 定义在类里面,所有的函数外面的变量.这个变量只有一份,是所有的对象共有的.在类外用“类.”来引用. 1.3 实例变量 ...
- C++成员变量内存对齐问题,ndk下非对齐的内存访问导致BUS_ADRALN
同样的代码,在vs下运行正常,在android ndk下却崩溃: signal 7(SIGBUS),code 1 (BUS_ADRALN),fault addr 0xe6b82793 Func(sho ...
- SpringMVC处理Date类型的成员变量方法
原文链接:http://www.tuicool.com/articles/aYfaqa 在使用 SpringMVC 的时候,我们可能需要将一个对象从 View 传递给 Controller .而当这个 ...
随机推荐
- [Unity][安卓]Unity和Android Studio 3.0 交互通讯(1)Android Studio 3.0 设置
[安卓]Android Studio 3.0 JDK安卓环境配置(2017.10) http://blog.csdn.net/bulademian/article/details/78387052 [ ...
- 学号 20175313《Java程序设计》 第七周学习总结
目录 一.教材学习内容总结 二.教材学习中的问题和解决过程 三.代码托管 四.心得体会 五.学习进度条 六.参考资料 一.教材学习内容总结 第八章主要内容 了解String类 常量对象:常量池中的数据 ...
- Python3学习之路~9.2 操作系统发展史介绍、进程与线程区别、线程语法、join、守护线程
一 操作系统发展史介绍 参考链接:http://www.cnblogs.com/alex3714/articles/5230609.html 二 进程与线程 进程: 对各种资源管理的集合 就可以称为进 ...
- Lists.newArrayList的一个小坑
把一个用户ID转换成List存储,最开始我使用的方法是: // 用户ID Integer userId = 120; // id 转 List List<integer> userIds ...
- FPC导通阻抗计算
pc线路板是有导电功能的,那么如何仅适用手工计算出线路的阻值能?那么就需要使用到一个公式: W*R*T=6000 W是指铜箔的宽度单位是密耳mil. T是指铜箔厚度单位是盎司oz. R是指铜箔的电阻单 ...
- Postman代码测试工具如何用?
1. 1)get请求,参数为map时, postman的传参 2)参数为基本数据类型的参数时 postman传参: 3)当参数在接口中动态获取时 postman传参: 2. 1)post请求,参数 ...
- c++简单程序设计 实验一
实验内容: 2-28 实现一个简单的菜单程序,运行时显示“Menu:A(dd) D(elete) S(ort) Q(uit),Selete one:”提示用户输入.A表示增加,D表示删除, S表示排序 ...
- Backup &recovery备份和还原
实践版本:MySQL5.7 备份类型(backup type)物理和逻辑备份(Physical Versus Logical Backup) 物理备份是指直接复制存储数据库内容的目录和文 ...
- 关于SimpleDateFormat安全的时间格式化线程安全问题
想必大家对SimpleDateFormat并不陌生.SimpleDateFormat 是 Java 中一个非常常用的类,该类用来对日期字符串进行解析和格式化输出,但如果使用不小心会导致非常微妙和难以调 ...
- validationEngine 使用
引入文件 环境在 jQuery 下 , 所有先要引入 jQuery <%--校验样式--%> <link rel="stylesheet" href=" ...