医疗行业网站建设方案,网站导航栏设计步骤,wordpress 调用随即文章,推广做网站莱芜SimpleDateFormat不是线程安全的。
SimpleDateFormat(下面简称sdf)类内部有一个Calendar对象引用#xff0c;它用来储存和这个sdf相关的日期信息#xff0c;例如sdf.parse(dateStr)#xff0c;sdf.format(date) 诸如此类的方法参数传入的日期相关String, Date等等#xff…SimpleDateFormat不是线程安全的。
SimpleDateFormat(下面简称sdf)类内部有一个Calendar对象引用它用来储存和这个sdf相关的日期信息例如sdf.parse(dateStr)sdf.format(date) 诸如此类的方法参数传入的日期相关String, Date等等 都是交由Calendar引用来存储的。这样就会导致一个问题如果多个线程共享sdf 也就会共享这个Calendar引用, 并且, 观察 sdf.parse() 方法,你会发现有如下的调用: Date parse() {calendar.clear(); //1: 清理calendar... //2: 执行一些操作, 设置 calendar 的日期什么的calendar.getTime(); //3: 获取calendar的时间}操作1和操作3会互相影响并且方法又不是同步方法所以存在线程安全问题。
如果 线程A 调用了 sdf.parse(), 并且进行了 calendar.clear()后还未执行calendar.getTime()的时候,线程B又调用了sdf.parse(), 这时候线程B也执行了sdf.clear()方法, 这样就导致线程A的的calendar数据被清空了(实际上A,B的同时被清空了).
又或者当 A 执行了calendar.clear() 后被挂起, 这时候B 开始调用sdf.parse()并顺利i结束, 这样 A 的 calendar内存储的的date 变成了后来B设置的calendar的date
解决方案
1每次用到都新建一个SimpleDateFormat做到不在线程间共享。
由于SimpleDateFormat创建耗费很大会涉及到大量的SimpleDateFormat对象的创建与销毁操作所以这种方式性能较差。适合对性能要求没那么高的场景。
2封装外部方法使用同步synchronize
这种方式在高并发场景下对性能影响较大。可能会出现线程长时间阻塞的情况。
3使用ThreadLocal
每个线程私有SimpleDateFormat对象既可以避免线程安全问题也可以避免方案1的缺点。
4使用JDK8的最新时间日期格式化API
如果你的jdk版本1.8那推荐使用java最新的时间日期API使用DateTimeFormatter它是线程安全的。