风中有朵雨做的云-ballbet贝博网站-ballbet贝博网页登录

作者:Felix zyf
来历:https://542869246.github.标签8io/2019/01风中有朵雨做的云-ballbet贝博网站-ballbet贝博网页登录/02/还在运用SimpleDateFormat?你的项目崩没?/

一、前语

日常开发中,咱们常常需求运用时刻相关风中有朵雨做的云-ballbet贝博网站-ballbet贝博网页登录类,提到时刻相关类,想必咱们对SimpleD风中有朵雨做的云-ballbet贝博网站-ballbet贝博网页登录ateFormat并不生疏。主要是用它进行时刻的格局化输出和解析,挺方便快捷的,可是风中有朵雨做的云-ballbet贝博网站-ballbet贝博网页登录SimpleDateFormat并不是一个线程安全的类。在多标签2线程情况下,会呈现异常,想必有经历的小伙伴也遇到过。下面咱们就来剖析剖析SimpleDateFormat为什么不安全?是怎样引发的?以及多线程下有那些SimpleDateFormat的处理方案?

先看看《阿里巴巴开发手册》关于SimpleDateFormat是怎样看待的:

二、问题场景复现

一般咱们运用SimpleDateFormat的时分会把它界说为一个静态变量,防止频频创立它的目标实例,如下代码:

是不是感觉没什么缺陷?单线程下天然没缺陷了,都是运用到多线程下就有大问题了。 测验下:

控制台打印成果:

你看这不崩了?部分线程获取的时刻不对,部分线程直接报java.lang.NumberFormatEx标签27ception:multiple points错,线程直接挂死了。

三、多线程不安全原因

由于咱们把标签5SimpleDateFormat界说为静态变量,那么多线程下SimpleDateFormat的实例就会被多个线程同享,B线程会读取到A线程的时刻,就会呈现时刻差异和其它各种问题。SimpleDateFormat和它承继的DateFormat类也不是线程安全的。

来看看SimpleDateFormat的format()办法的源码:

留意, calendar.setTime(date),SimpleDateFormat的format办法实际操作的便是Calendar

由于咱们声明风中有朵雨做的云-ballbet贝博网站-ballbet贝博网页登录SimpleDateFormat为static变量,那么它的Calendar变量也便是一个同享变量,能够被多个线程拜访

假定线程A履行完calendar.setTime(dat标签19e),把时刻设置成2019-01-02,这时分被挂起,线程B获标签25得CPU履行权。线程B也履行到了calendar.setTime(date),把时刻设置为2019-01-03。线程挂起,线程A持续走,calendar还会被持续运用(s标签5ubFormat办法),而这时calendar用的是线程B设置的值了,而这便是引发问题的本源,呈现时刻不对,线程挂死等等。

其实SimpleDateFormat源码上作者也给过咱们提示:

意思便是:

日期格局不同步。主张为每个线程创立独自的格局实例。假如多个线程一起拜访一种格局,则有必要在外部同步该格局。

四、处理方案

只在需求的时分创立新实例,不必stat标签20ic润饰。

如上代码,仅在需求用到的当地创立一个新的实例,就没有线程安全问题,不过也加剧了创立目标的担负,会频频地创立标签3和毁掉目标,功率较低

synchronized大法好

简略粗犷,synchronized往上一套也能够处理线程安全问题,缺陷天然便是并发量大的时分会对功能有影响,线程堵塞

ThreadLocal

ThreadLocal能够保证每个线程都能够得到独自的一个SimpleDateFormat的目标,那么天然也就不存在竞赛问题了。

根据JDK1.8的DateTimeFormatter

也是《阿里巴巴开发手册》给咱们的处理方案,对之前的代码进行改造:

运转成果风中有朵雨做的云-ballbet贝博网站-ballbet贝博网页登录就不贴了,不会呈现报错和时刻不精确的问题。

DateTimeFor风中有朵雨做的云-ballbet贝博网站-ballbet贝博网页登录matter源码上作者也加注释说明晰,他的类是标签9不可变的,并且是线程标签9安全的。

OK,现在是不是能够对你项目里的日期东西类进行一波优化了呢?标签5

发表评论

电子邮件地址不会被公开。 必填项已用*标注