java全局变量引起的并发问题「建议收藏」

java全局变量引起的并发问题「建议收藏」最近刚完成了一个短彩信群发平台的开发工作,系统采用springmvc+hibernate+jdbctemplate+mysql架构。其中遇见许多问题,闲暇之余记录下来以避免在后续项目中再犯同样的错误。先看下面小段代码,一个controller,一个service。       controller.java代码:    ……..    @Autowired

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

最近刚完成了一个短彩信群发平台的开发工作,系统采用springmvc+hibernate+jdbctemplate+mysql架构。其中遇见许多问题,闲暇之余记录下来以避免在后续项目中再犯同样的错误。

先看下面小段代码,一个controller,一个service。

       controller.java代码:
    ……..
    @Autowired
     private XXXService xxxService;
    ……..
    @RequestMapping(“/doXXX.do”)
    public void doXXX(){

        …..
        xxxService.saveXXX(String content,….);
        …..
    }
    XXXService.java代码:
    private String content;
    ……
    private void init(){//清空请求参数
        content = null;
        ……
    }
    public boolean saveXXX(String content, ……){

        this.init(content, …);
        this.content = content;
        //业务逻辑处理
    }

    以上这段代码在访问量不构成并发时不会出现什么问题。 但当一个请求还未完成,另一个请求已经开始执行的情况下就会出现问题(并发): 第二个请求执行执行init()方法会将第一个请求的content变量设置为null或它本身的值,这样数据就被篡改了。

    编码者这样写的目的是因为content等变量需要在多个方法中使用,而且变量很多,但又不想通过方法参数的方式来传递,故使用成员变量。

    先看看为什么会出现这种情况。 由于系统采用springmvc框架,springmvc核心控制器DispatcherServlet 默认为每个controller生成单一实例来处理所有用户请求,所以在这个单一实例的controller中,它的XXXService也是一个实例处理所有请求, 这样XXXService的成员变量就被所有请求共享。这样就会出现并发请求时变量内容被篡改的问题。

    那么出现这种问题如何解决呢? 
    第一种方式: 既然是全局变量惹的祸,那就将全局变量都编程局部变量,通过方法参数来传递。
    第二种方式: jdk提供了java.lang.ThreadLocal,它为多线程并发提供了新思路。 (当使用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本
         那么在什么地方使用ThreadLocal呢? 什么变量是请求公用的就将该变量托付给ThreadLocal来管理其线程副本, 所以我们在xxxService中使用它。
        XXXService.java代码:
        private ThreadLocal<String> contentTL = new ThreadLocal<String>();
        //private String content;使用contentTL代替content;
        ……
        public boolean saveXXX(String content, ……){

            this.contentTL.set(content);  

            //业务逻辑处理
            //在各方法中使用content时候用this.contentTL.get()代替
    }  

     此类并发篡改数据的问题,可以在开发工具中设置断点调试的方式来模拟并发。即第一次请求运行到断点时,查看content内容,并且不让程序继续往下运行,同时再发起一个请求,查看content内容。 如内容是第一次请求的内容,并且让第一个请求跑完后,第二个请求到断线处的content正确时,可以确定不会出现并发问题。

     如果有spring配置文件那就直接加上scope=”prototype”就行啦

原文地址:http://my.oschina.net/robolin/blog/78395

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/171746.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • Apache配置虚拟主机_apache启动但是访问不到

    Apache配置虚拟主机_apache启动但是访问不到Apache配置虚拟主机无效本今天电脑重新安装了一下apache,结果配置好虚拟域名之后,却一直无法访问;localhost一直是显示itworks状态;配置好了虚拟域名之后,输入任何配置的域名也都是显示itworks状态;而通过127.0.0.1是可以看到文件目录的;经过再三检查,最后发现问题是在httpd_conf文件上,只需要注释掉ServerNamelocalhos

    2022年9月18日
    1
  • js实现的A星算法[通俗易懂]

    js实现的A星算法[通俗易懂]一、前言最近在写js的slg游戏,需要用到a星算法。之前用python写过https://blog.csdn.net/qq_39687901/article/details/80753433,现在再用js写一遍。二、源码//二维数组functionArray2D(w,h,num){vardata=[];vardefault_num=num|…

    2022年9月27日
    5
  • Pytest(6)重复运行用例pytest-repeat[通俗易懂]

    Pytest(6)重复运行用例pytest-repeat[通俗易懂]前言平常在做功能测试的时候,经常会遇到某个模块不稳定,偶然会出现一些bug,对于这种问题我们会针对此用例反复执行多次,最终复现出问题来。自动化运行用例时候,也会出现偶然的bug,可以针对单个用例,

    2022年7月29日
    9
  • 按位取反运算符的运算举例_按位与按位或按位异或运算符

    按位取反运算符的运算举例_按位与按位或按位异或运算符前言:位运算符是用来对二进制位进行操作的c语言中有6种位运算符:&按位与[链接]:https://blog.csdn.net/weixin_42837024/article/details/98736834|按位或[链接]:https://blog.csdn.net/weixin_42837024/article/details/98745019^按位异或[链接]…

    2022年8月15日
    9
  • 软件工程师业绩简要描述(优秀员工工作业绩和自我评价)

    1/9JAVA软件工程师简历自我评价具有很强的团队精神,有良好的组织和协调能力,有强烈的集体荣誉感。自学能力强,喜欢钻研新技术,敢于面对和克服困难。熟练使用spring+struts+hibernate整合开发。熟练使用jsp、servlet、jstl、jdbc下的编程开发。熟练使用eclipseide开发工具,熟练掌握tomcat等web容器以及j2ee容器的配置以及部署,能够使用junit进行…

    2022年4月13日
    376
  • 仿微博php生成短网址

    htmlcodephpcode推荐:http://www.cnblogs.com/roucheng/p/3528396.html

    2021年12月27日
    41

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号