Spring MVC 线程安全问题的思考

在读一些博文的时候发现有些文章对SpringMVC的Controller线程安全的验证并不正确,比如没有探究controller线程不安全的具体原因,比如将请求线程当做controller多例的证明,以下将验证。
http://bbs.csdn.net/topics/390894585
http://bbs.csdn.net/topics/390891861#post-398241838

1.request请求线程与controllte的关系是什么?

简易的验证方法代码


在网上随便下载了一个压力测试工具


测试结果如下



从打印的日志可以看出,请求时多线程请求的,但是每次请求过来调用的Controller对象都是一个,而不是一个请求过来就创建一个controller对象

那为什么说controller是不安全的呢?

原因就在于如果这个controller对象是单例的,那么如果不小心在类中定义了类变量,那么这个类变量是被所有请求共享的,这可能会造成多个请求修改该变量的值,出现与预期结果不符合的异常。

接下来将验证多并发的情况下controller的线程不安全的具体表现、通过配置实现controller多例

在单例的情况下 相当于所有类变量对于每次请求都是共享的,每一次请求对类变量的修改都是有效的

private static int st=0;
private int index=0;
@RequestMapping(value="/testcontrollersinglon",method=RequestMethod.GET)
	@ResponseBody
	public String testControllerSinglon(HttpServletRequest request){
		try {
			System.out.println(st++ + " | " + index++);
			return "yes";
		} catch (Exception e) {
			e.printStackTrace();
			return "error";
		}
	}
看一下打印的日志



通过日志可以看出 变量index为所有请求共享 

那有没有办法让controller不以单例而以每次请求都重新创建的形式存在呢?

答案是当然可以,只需要在类上添加注解@Scope("prototype")即可,这样每次请求调用的类都是重新生成的(每次生成会影响效率)

添加@Scope("prototype")后我们再看看日志就会看出区别了


虽然这样可以解决问题,但增加了时间成本,总让人不爽,还有其他方法么?答案是肯定的!使用ThreadLocal来保存类变量,将类变量保存在线程的变量域中,让不同的请求隔离开来

这里写图片描述 
如果我的方法有帮到你,不妨请杯水喝吧?


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值