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

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


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)
全栈程序员-站长的头像全栈程序员-站长

相关推荐

  • kafuka生产者和消费者及配置

    kafuka生产者和消费者及配置#kafka生产者配置#kafka集群kafka.bootstrap.servers=ip:端口#发送端确认模式kafka.acks=all#发送失败重试次数kafka.retries=10#批处理条数kafka.batch.size=16384#延迟统一收集,产生聚合,然后批量发送kafka.linger.ms=100#批处理缓冲区kafka.buffer.memo…

    2022年6月3日
  • 游戏报错0xc000007b(错误状态0xc0000020)

    最后更新:2019-2-28如图,0xc000007b这个错误使无数玩家烦恼。问题描述:出现这个错误,可能是硬件的问题,也可能是软件的问题。但是,由于硬件引起该问题的概率很小,并且除了更换硬件之外没有更好的解决方法,因此本文将详细介绍如何通过软件解决此问题,这也是大家最关心的。由于本文阅读用户众多,大家对于电脑故障解决的熟悉程度也不一样,因此本文致力…

    2022年4月10日
  • 白话空间统计二十四:地理加权回归(二)

    白话空间统计二十四:地理加权回归(二)六千多字的大篇……诚意满满啊……橘生淮南则为橘,生于淮北则为枳,叶徒相似,其实味不同。所以然者何?水土异也。——《晏子春秋·内篇杂下》水土不服、南北差异,(包括地域歧视)是自古以来的一个大命题……正如在(伪)吃货的眼中,中国的地图是这样的:为什么说上面是伪?吃货呢,因为在真?吃货眼中的中国地图,是这样的:这就是具有全局眼(胃)光(口)和局部眼(胃)光(口),

    2022年10月7日
  • redis系列之——一致性hash算法「建议收藏」

    redis系列之——一致性hash算法「建议收藏」一致性hash算法你了解吗?什么时候使用?解决什么问题?redis集群模式使用了一致性hash算法了吗?数据分片(sharding)分布式数据存储时,经常要考虑数据分片,避免将大量的数据放在单表或单库中,造成查询等操作的耗时过长。比如,存储订单数据时使用三个mysql库(编号0,1,2),当一条订单数据过来时,对订单id求hash后与机器数量取模,hash(orderId)%3,假如得到的结果是2,则这条数据会存储到编号为2的mysql中。分表分库存储时,根据数据库的主键或唯一键做hash,然后跟

    2022年9月29日
  • pycharm菜单栏不见了_pycharm左侧项目栏隐藏

    pycharm菜单栏不见了_pycharm左侧项目栏隐藏ctrl+Alt+shif打开搜索窗口,然后输入Experimentalfeatures 取消linux.native.menu选项的复对勾,应用更改并关闭,重启PyCharm。

    2022年8月25日
  • mysql的text与tinytext,MySQL中的VARCHAR(255)和TINYTEXT字符串类型有什么区别?

    mysql的text与tinytext,MySQL中的VARCHAR(255)和TINYTEXT字符串类型有什么区别?What’sthedifferencebetweenVARCHAR(255)andTINYTEXTstringtypesinMySQL?Eachofthemallowstostorestringswithamaximumlengthof255characters.Storagerequirementsarealsothesame.When…

    2022年8月13日

发表回复

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

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