zoukankan      html  css  js  c++  java
  • 测试SpringMVC可能出现的线程安全问题

    SpringMVC的Controller默认是单例的,对于同一个Controller而言,在整个web生命周期内只有一个对象。如果在Controller里写了一个成员变量,这个变量是对所有线程可见的。

    @Slf4j
    @Controller
    public class TestController {
    
        private List<String> list = new ArrayList<>();
      
        @RequestMapping(method = RequestMethod.GET, value = "/test")
        public ModelAndView test(Model model) {
            list.add(this.hashCode() + "");
            ModelAndView modelAndView = new ModelAndView("test");
            modelAndView.addObject("name", list.hashCode() + "--" +list.size());
            return modelAndView;
        }
    }
    

    页面模板如下

    <!DOCTYPE html>
    <html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title></title>
    </head>
    <body>
    Hello ${name}
    </body>
    </html>
    



    前后两次请求list的size在发生变化说明两次请求操作的是同一个list对象。由于list在添加对象后hashCode也会发生变化,所以两次请求后的list的hashCode也发生了变化。

    如果将Controller设置为原型模式,则每次请求都会new一个Controller的对象,此时不会出现线程安全问题。

    @Slf4j
    @Scope("prototype")
    @Controller
    public class TestController {
    //······
    }
    


    此时虽然可能避免上述的线程安全问题,但是jvm必须为每次请求创建新的对象,在请求完成之后销毁对象,这必然会增加系统的性能开销。

    附:ArrayList计算hashCode的源码

    public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> {
        public int hashCode() {
            int hashCode = 1;
            for (E e : this)
                hashCode = 31*hashCode + (e==null ? 0 : e.hashCode());
            return hashCode;
        }
    }
    
  • 相关阅读:
    phpstorm 2016.3.2 的最新破解方法(截止2017-2-20)
    在GitHub多个帐号上添加SSH公钥
    mac laravel 环境变量设置bash_profile
    Laravel的三种安装方法总结
    laravel登录后台500错误!
    composer镜像安装laravel
    phpstorm 代码按列对齐
    .DS_Store 文件是什么?Mac下面如何禁止.DS_Store生成
    如何在Mac下显示Finder中的所有文件
    PHP_环境配置_python脚本_2017
  • 原文地址:https://www.cnblogs.com/umgsai/p/6895715.html
Copyright © 2011-2022 走看看