springMVC一个Controller处理所有用户请求的并发问题(转)
springMVC一个Controller处理所有用户请求的并发问题
有状态和无状态的对象基本概念:
有状态对象(Stateful Bean),就是有实例变量的对象 ,可以保存数据,是非线程安全的。一般是prototype scope。
无状态对象(Stateless Bean),就是没有实例变量的对象,不能保存数据,是不变类,是线程安全的。一般是singleton scope。
如Struts2中的Action,假如内部有实例变量User,当调用新增用户方法时,user是用来保存数据,那么此action是有状态对象。多个线程同时访问此action时 会造成user变量的不一致。所以action的scope要设计成prototype,或者,User类放到threadLocal里来保持多个线程不会造成User变量的乱串(此种场景没必要放到threadLocal内)。
而Service内部一般只有dao实例变量 如userDao, 因为userDao是无状态的对象(内部无实例变量且不能保存数据),所以service也是无状态的对象。
public class XxxAction{
// 由于多线程环境下,user是引用对象,是非线程安全的
public User user;
......
}
public class XxxService {
// 虽然有billDao属性,但billDao是没有状态信息的,是Stateless Bean.
BillDao billDao;
......
}
对于那些会以多线程运行的单例类
局部变量不会受多线程影响,
成员变量会受到多线程影响。
多个线程调用同一个对象的同一个方法:
如果方法里无局部变量,那么不受任何影响;
如果方法里有局部变量,只有读操作,不受影响;存在写操作,考虑多线程影响值;
例如Web应用中的Servlet,每个方法中对局部变量的操作都是在线程自己独立的内存区域内完成的,所以是线程安全的。
对于成员变量的操作,可以使用ThreadLocal来保证线程安全。
springMVC中,一般Controller、service、DAO层的scope均是singleton;
每个请求都是单独的线程,即使同时访问同一个Controller对象,因为并没有修改Controller对象,相当于针对Controller对象而言,只是读操作,没有写操作,不需要做同步处理。
Service层、Dao层用默认singleton就行,虽然Service类也有dao这样的属性,但dao这些类都是没有状态信息的,也就是 相当于不变(immutable)类,所以不影响。
Struts2中的Action因为会有User、BizEntity这样的实例对象,是有状态信息 的,在多线程环境下是不安全的,所以Struts2默认的实现是Prototype模式。在Spring中,Struts2的Action中scope 要配成prototype作用域。
Spring并发访问的线程安全性问题
由于Spring MVC默认是Singleton的,所以会产生一个潜在的安全隐患。根本核心是instance变量保持状态的问题。这意味着每个request过来,系统都会用原有的instance去处理,这样导致了两个结果:
一是我们不用每次创建Controller,
二是减少了对象创建和垃圾收集的时间;
由于只有一个Controller的instance,当多个线程同时调用它的时候,它里面的instance变量就不是线程安全的了,会发生窜数据的问题。
当然大多数情况下,我们根本不需要考虑线程安全的问题,比如dao,service等,除非在bean中声明了实例变量。因此,我们在使用spring mvc 的contrller时,应避免在controller中定义实例变量。
如:
publicclassControllerextendsAbstractCommandController{
......
protectedModelAndView handle(HttpServletRequest request,HttpServletResponse response,
Object command,BindException errors)throwsException{
company =................;
}
protectedCompany company;
}
在这里有声明一个变量company,这里就存在并发线程安全的问题。
如果控制器是使用单例形式,且controller中有一个私有的变量a,所有请求到同一个controller时,使用的a变量是共用的,即若是某个请求中修改了这个变量a,则,在别的请求中能够读到这个修改的内容。。
有几种解决方法:
1、在控制器中不使用实例变量
2、将控制器的作用域从单例改为原型,即在spring配置文件Controller中声明 scope="prototype",每次都创建新的controller
3、在Controller中使用ThreadLocal变量
这几种做法有好有坏,第一种,需要开发人员拥有较高的编程水平与思想意识,在编码过程中力求避免出现这种BUG,而第二种则是容器自动的对每个请求产生一个实例,由JVM进行垃圾回收,因此做到了线程安全。
使用第一种方式的好处是实例对象只有一个,所有的请求都调用该实例对象,速度和性能上要优于第二种,不好的地方,就是需要程序员自己去控制实例变量的状态保持问题。第二种由于每次请求都创建一个实例,所以会消耗较多的内存空间。
所以在使用spring开发web 时要注意,默认Controller、Dao、Service都是单例的
---------------------------------------------------------------------------------------------------------------------------------------------------------
SpringMVC默认创建bean是单例的,高并发情况下,如何保证性能的?
首先在大家的思考中,肯定有影响的,你想想,单例顾名思义:一个个排队过... 高访问量的时候,你能想象服务器的压力了... 而且用户体验也不怎么好,等待太久~
实质上这种理解是错误的,Java里有个API叫做ThreadLocal,spring单例模式下用它来切换不同线程之间的参数。用ThreadLocal是为了保证线程安全,实际上ThreadLoacal的key就是当前线程的Thread实例。单例模式下,spring把每个线程可能存在线程安全问题的参数值放进了ThreadLocal。这样虽然是一个实例在操作,但是不同线程下的数据互相之间都是隔离的,因为运行时创建和销毁的bean大大减少了,所以大多数场景下这种方式对内存资源的消耗较少,而且并发越高优势越明显。
单例模式是spring推荐的配置,它在高并发下能极大的节省资源,提高服务抗压能力
springMVC一个Controller处理所有用户请求的并发问题(转)的更多相关文章
- springMVC一个Controller处理所有用户请求的并发问题
有状态和无状态的对象基本概念: 有状态对象(Stateful Bean),就是有实例变量的对象 ,可以保存数据,是非线程安全的.一般是prototype scope. 无状态对象(Stateless ...
- SpringMVC实现一个controller写多个方法
MultiActionController与ParameterMethodNameResolver在一个Controller类中定义多个方法,并根据使用者的请求来执行当中的某个方法,相当于Struts ...
- SpringMVC实现一个controller里面有多个方法
我们都知道,servlet代码一般来说只能在一个servlet中做判断去实现一个servlet响应多个请求, 但是springMVC的话还是比较方便的,主要有两种方式去实现一个controller里能 ...
- SpringMVC从Controller跳转到另一个Controller(转)
http://blog.csdn.net/jackpk/article/details/44117603 [PK亲测] 能正常跳转的写法如下: return "forward:aaaa/bb ...
- springMVC修改用户请求内容
最近在做一个微信相关的网站,很多地方涉及到微信表情的输入,导致内容无法插入到数据库,虽然有用到一个表情过滤的工具类,但是需要过滤的地方比较多,于是想到在过滤器中过滤用户请求的内容. request这个 ...
- restful风格url Get请求查询所有和根据id查询的合并成一个controller
restful风格url Get请求查询所有和根据id查询的合并成一个controller的方法 原代码 // 127.0.0.1:8080/dep/s @ApiOperation(value=&qu ...
- SpringMVC从Controller跳转到另一个Controller
1. 需求背景 需求:spring MVC框架controller间跳转,需重定向.有几种情况:不带参数跳转,带参数拼接url形式跳转,带参数不拼接参数跳转,页面也能显示. 本来以为挺简单的一件事 ...
- SpringMVC从Controller跳转到还有一个Controller
1. 需求背景 需求:spring MVC框架controller间跳转,需重定向.有几种情况:不带參数跳转.带參数拼接url形式跳转,带參数不拼接參数跳转,页面也能显示. 本来以为挺简单的一件事情. ...
- springmvc怎么重定向,从一个controller跳到另一个controller
第一种情况,不带参数跳转: 方法一:使用ModelAndView return new ModelAndView("redirect:/toList"); 这样可以重定向到toL ...
随机推荐
- Spring 中 Bean 的生命周期
所谓 Bean 的生命周期,就是一个 Bean 从创建到销毁,所经历的各种方法调用.大致包含下面几个方法(不是全部) Bean 的实例化,调用了构造方法. 使用 setter 方法填充属性. 一旦依赖 ...
- MySql:SELECT 语句(三) WHERE 指定查询条件
1.WHERE 子句条件操作符 包括:> .<.>=.<=.!= .=.BETWEEN ... AND ...(在指定的两个值之间) 示例: 1)select * from s ...
- 剑指offer例题——反转链表
题目描述 输入一个链表,反转链表,输出新链表的表头 程序编写 将链表反转 public class Solution { public ListNode ReverseList(ListNode he ...
- mobilenet之Depthwise +Pointwise
我们知道,mobilenet是适用于移动端的深度学习网络,主要优点是参数少.模型小.准确率相比一些传统卷积损失少等特点. mobileNet之所以这么ok,是因为引入了Depthwise +Point ...
- VS2010 Chart控件(一)Chart控件在ASP.NET网站中的应用示例详解(C#语言)
步骤如下: 1. Chart控件(一)Chart控件在ASP.NET网站中的应用示例详解(C#语言)" title="VS2010 Chart控件(一)Chart控件在ASP.NE ...
- 引用计数——深拷贝&浅拷贝
下面是用代码实现: private: char *data; size_t use_count; public: //构造函数 String_rep() { if(str == NULL) { dat ...
- cdnbest获取,删除,增加,修改域名列表,高级设置api示例
<?php $uid = 28; $vhost = 'asdfw'; $token = getToken($uid, $vhost); print_r($token); //获取token fu ...
- ppt复制文本框文字到word的方法
打开ppt按Alt+F11,插入--模块, 选中“工具”--“引用”--MicroSoft Word .. 复制代码: Sub Main() On Error Resume Next Dim tem ...
- FortiGate抓包 Sniffer
1.图形界面抓包 系统管理--网络--数据包捕获 选择添加好的数据捕获,点击"运行"开关抓包:抓取包后,可以点击"下载"将抓取的数据包保存的本地磁盘,可以用wi ...
- java基础 ----- 选择结构
--------- 流程控制 ------ 流程图 ------ 基本的 if 选择结构 import java.util.Scanner; public class GetPr ...