Spring controller、service的单例模式

来源:互联网 发布:js 字符串转时间戳 编辑:程序博客网 时间:2024/05/16 19:36

spring 中的单例模式在并发的情况下是怎么保证数据不会混乱的??

首先我们知道Spring 中controller、service、dao都为单例模式(注:默认状态)。

既然是单例,那么在并发的情况下,会发生什么?

废话不多说,看代码。

后台:

@Controller@RequestMapping("/user")public class UserController {    @Autowired    private UserServiceI userService;        private int i;        @POST    @RequestMapping("test.do")    @ResponseBody    public Result test(User user) {        System.out.println(user.getUserName()+":进入方法");        i++;        System.out.println("开始阻塞");        try {            Thread.sleep(5000);        } catch (InterruptedException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }        System.out.println("阻塞结束");        System.out.println("i="+i);        System.out.println("此时UserName:"+user.getUserName());        return null;    }}
前台:
<div><fieldset><form action="<%=basePath%>user/test.do" method="post"><input name="userName"><br>                                 <input type="submit" value="提交"></form></fieldset></div>
两台电脑:一个输入1,一个输入2,点击提交,提交时间间隔1秒左右即可。

控制台输出:

1:进入方法开始阻塞2:进入方法开始阻塞阻塞结束i=2此时UserName:1阻塞结束i=2此时UserName:2

看到,成员变量 i 受到了并发的影响,而我们表单提交的userName参数,并未收到并发的影响。

再测,继续提交表单,看到 i 的值一直在自增,对于我来说这是一个吓人的发现,作了这么久的程序员,刚发现这个问题。。。多久就不透露了,丢人。。


下面是来自博客的答案:

成员方法也是共享的,为什么就不会出现问题呢?
==================================================
java 里,每个线程都有自己独享的空间,也就是栈内存。线程在调用方法的时候,会创建一个栈帧。也就是说调用一个方法的时候,也就是一个栈帧的入栈过程,该方法执行完毕,栈帧也就出栈了。
换句话讲,成员方法对于每个线程事实上是私有的,而不是你表面看上去的那样是 "共享" 的。

那么为什么成员变量会出问题呢?
==================================================
如你所知道的,每个新建对象都存放在堆中,每个持有该对象引用的线程,都可以访问到它(只要你有那个权限)。
这也就是说,成员变量对于每个线程,事实上是共享的。


而service层呢?dao呢?

经过测试,与controller结论相同。

1 0
原创粉丝点击