2019独角兽企业重金招聘Python工程师标准>>>

诸位Java程序员,想必大家对SimpleDateFormat并不陌生。不过,你是否知道,SimpleDateFormat不是线程安全的(thread safe)。这意味着,下面的代码是错误的:

class Sample {private static final DateFormat format = new SimpleDateFormat("yyyy.MM.dd");public String getCurrentDateText() {return format.format(new Date());}
}

从功能的角度上看,单独执行这段代码是没有问题的,但放到多线程环境下,因为SimpleDateFormat不是线程安全的,这段代码就会出错。所以,要想让这段代码正确,我们只要稍做微调:

public class Sample {public String getCurrentDateText() {return new SimpleDateFormat("yyyy.MM.dd").format(new Date());}
}

不知你是否注意到,这里的调整只是由原来的共享format这个变量,变成了每次调用这个方法时创建出一个新的SimpleDateFormat变量。

作为一个专业程序员,我们当然知道,相比于共享一个变量的开销要比每次创建小。之所以我们必须这么做,是因为SimpleDateFormat不是线程安全的。但从SimpleDateFormat提供给我们的接口上来看,实在让人看不出它与线程安全有何相干。那接下来,我们就要打开JDK的源码,看一下其中的代码之丑。

果你手头没有JDK的源码,这里是个不错的参考。

在format方法里,有这样一段代码:

calendar.setTime(date);

其中,calendar是DateFormat的protected字段。这条语句改变了calendar,稍后,calendar还会用到(在subFormat方法里),而这就是引发问题的根源。

想象一下,在一个多线程环境下,有两个线程持有了同一个SimpleDateFormat的实例,分别调用format方法:

线程1调用format方法,改变了calendar这个字段。
    中断来了。
    线程2开始执行,它也改变了calendar。
    又中断了。
    线程1回来了,此时,calendar已然不是它所设的值,而是走上了线程2设计的道路。
    BANG! 稍微花点时间分析一下format的实现,我们便不难发现,用到calendar,唯一的好处,就是在调用subFormat时,少了一个参数,却带来了这许多的问题。其实,只要在这里用一个局部变量,一路传递下去,所有问题都将迎刃而解。

这个问题背后隐藏着一个更为重要的问题:无状态。

无状态方法的好处之一,就是它在各种环境下,都可以安全的调用。衡量一个方法是否是有状态的,就看它是否改动了其它的东西,比如全局变量,比如实例的字段。format方法在运行过程中改动了SimpleDateFormat的calendar字段,所以,它是有状态的。

写程序,我们要尽量编写无状态方法。

转载于:https://my.oschina.net/bairrfhoinn/blog/62758

郑晔:代码之丑 无状态方法相关推荐

  1. spring期刊状态_无状态Spring安全性第2部分:无状态认证

    spring期刊状态 Spring Stateless Security系列的第二部分是关于以无状态方式探索身份验证的方法. 如果您错过了有关CSRF的第一部分,可以在这里找到. 因此,在谈论身份验证 ...

  2. csrf spring_无状态Spring安全性第1部分:无状态CSRF保护

    csrf spring 如今,随着RESTful架构变得越来越标准,可能值得花一些时间重新考虑当前的安全方法. 在这一小系列博客文章中,我们将探索以无状态方式解决与Web相关的安全性问题的几种相对较新 ...

  3. 无状态Spring安全性第2部分:无状态身份验证

    Spring Stateless Security系列的第二部分是关于以无状态方式探索身份验证的方法. 如果您错过了CSRF的第一部分,可以在这里找到. 因此,在谈论身份验证时,其全部内容就是让客户端 ...

  4. 无状态Spring安全性第1部分:无状态CSRF保护

    如今,随着RESTful架构变得越来越标准,可能值得花一些时间重新考虑当前的安全方法. 在这个小系列的博客文章中,我们将探索一些以无状态方式解决与Web相关的安全问题的相对较新的方法. 这第一篇文章是 ...

  5. react中的无状态函数式组件

    无状态函数式组件,顾名思义,无状态,也就是你无法使用State,也无法使用组件的生命周期方法,这就决定了函数组件都是展示性组件,接收Props,渲染DOM,而不关注其他逻辑. 其实无状态函数式组件也是 ...

  6. Spring 有状态bean 无状态bean

    https://blog.csdn.net/anyoneking/article/details/5182164 在Spring的Bean配置中,存在这样两种情况: [xhtml] view plai ...

  7. Python爬虫之selenium对标签页切换、切换frame标签、cookie处理、执行js代码、开启无界面、以及使用代理ip和替换user-agent等方法

    一.selenium对标签页切换.切换frame标签.cookie处理.执行js代码.开启无界面.以及使用代理ip和替换user-agent等方法 (一).selenium标签页的切换 当seleni ...

  8. PHP无状态对象,(PHP)基于Token的身份验证中对无状态的理解

    假设我们设计的Token储存的信息为: 用户名.发行时间.过期时间.签名 在用户登录成功后,我们获取到用户的用户名.此时的时间戳,并将它们和我们设置的过期时间拼接在一起,组成一个字符串,假设为: $i ...

  9. 方法功能从无参方法、含参方法到重载方法

    时间紧张,先记一笔,后续优化与完善. 一.无参方法 a.无参方法法语: 访问修饰符> 返回类型 <方法名>(){ //方法的体主 } b.义定 什么是无参方法?所谓无参方法即形如,诸 ...

最新文章

  1. linux C非阻塞延时,linux 非阻塞式socket编程求助。。
  2. C++中对String的各种操作
  3. ORACLE11G自动维护任务简析
  4. UGUI 下拉滚动框
  5. Wing IDE 4.1破解教程
  6. jQuery原理第三天
  7. goto php 源码,GoToPHP
  8. c/c++教程 - 2.1 程序的内存模型 内存四区 代码区 全局区 堆区 栈区 new操作符
  9. 如何在命令行下运行kettle的作业(job)和转换(transform)
  10. 【BFS】LeetCode 130. Surrounded Regions
  11. 关于Hive在主节点上与不在主节点上搭建的区别之谈
  12. 一键破解宝塔面板的专业版本权限
  13. mac显示所有文件后缀名
  14. 熵增定律与人际关系-整理
  15. Ubuntu主机合盖子不休眠
  16. 光子虚拟机_光速虚拟机app下载-光速虚拟机安卓版 v1.1.1 - 安下载
  17. 【入坑Java第二天】
  18. #matplotlib#如何设置坐标轴显示时间的范围
  19. Selenium自动化测试代理问题
  20. iOS UIButton 图标与标题位置调整

热门文章

  1. 有赞融资10亿港元 腾讯领投加紧布局产业互联网
  2. 秋色园QBlog技术原理解析:Web之页面处理-内容填充(八)
  3. Retrofit2.0
  4. 【redis】2.redis可视化工具安装使用
  5. Linux学习总结(7)——阿里云centeros服务器上安装 jdk,tomcat,mysql
  6. Linux中升级更新命令yum upgrade和yum update的区别
  7. jenkins执行xctool命令出现command not found问题解决方法
  8. windows文件名非法字符过滤检测-正则表达式
  9. Android自定义View:MeasureSpec的真正意义与View大小控制
  10. cocos2d-x之读取json文件