摘要:我们知道SimpleDateFormat是不安全的线程。本文将介绍5种解决方案,以确保线程安全。
在Java8之前,要格式化日期,您需要使用SimpleDateFormat。
但是,我们知道SimpleDateFormat是不安全的线程。处理它时必须小心。您必须锁定或不能定义为静态。该对象在方法中可用并格式化。它非常麻烦,反复的新对象也增加了内存开销。
让我们看一下SimpleDateFormat的源代码,首先查看格式方法:
问题在于成员变量日历。如果使用SimpleDateFormat,请使用静态定义它,然后SimpleDateFormat将变为共享变量。calendar可以通过多个线程访问SimpleDateFormat。
SimpleDateFormat的解析方法也是不安全的线程:
可以从源代码中看到它,最后调用** parsedate = calb.espablish(calendar).getTime();**获取返回值。该方法的参数是日历,并且可以通过多个线程访问日历,并且存在不安全线程的问题。
让我们看一下** calb.epblablish(日历)**的源代码
calb.espblish(日历)方法连续称为cal.clear()和cal.set(),首先清理值,然后设置值。但是,这两个操作不是原子,也没有线程安全机制为了确保在多线程并发时,可能会导致CAL值的问题。
false出现两次,表明该线程不安全。它仍然异常,这很严重。
当使用SimpleDateFormat对象进行格式或解析时,它被定义为局部变量。它可以确保线程的安全性。
从图可以看出,已保证线程安全性,但是不建议在高并发场景中使用此方案,因为将创建大量的简单构造对象来影响性能。
SimpleDateFormat对象仍定义为全局变量,然后当需要简单的格式时间以进行格式化时间时,然后使用同步保证线程安全性。
如图所示,线程是安全的。定义全局变量SimpleDateFormat,它减少了创建大量SimpleDateFormat对象的丢失。但是,使用同步锁,只有线程可以同时执行锁定代码块,这将影响高并发条件下的性能。但不建议在高点场景中使用此方案
添加锁定锁和同步锁的原理是相同的,它们使用锁定机制来确保线程的安全性。
从结果可以看出,添加锁定锁也可以确保线程安全性。应该注意的是,必须释放锁。该代码将lock.unlock()添加到决赛。
在高并发状态的情况下,它将影响性能。不建议该方案在高的并发场景中使用
使用ThreadLocal来确保每个线程都有SimpleDateFormat对象的副本。这可以确保线程的安全性。
线路的使用可以确保线程安全性和效率。适合高并发场景。
使用DateTimeFormatter而不是SimpleDateFormat(DateTimeFormatter是线程-Safe,Java 8+支持)
DateTimeFormatter简介门户网站:Bowen教导您了解Java源代码的日期和时间用法
使用DateTimeFormatter来确保线程安全性和效率很高。适合高并发场景。
使用FastDateFormat替换SimpleDateFormat(FastDateFormat是线程-Safe,Apache Commons lang Package支持,不限于Java版本)
使用FastDateFormat可以确保线程安全性和效率很高。适合高并发场景。
源代码中的CALENDER是通过格式方法创建的,并且肯定不会发生Settime的线程安全问题。该线程安全疑问已解决。您必须考虑性能问题吗?
让我们看看如何获得fastDateFormat
查看相应的源代码
这里有一个缓存,似乎使用了缓存,并且低头看。
将cetinstance方法添加到contrentMap中以减慢和提高性能。我们知道consurrentMap也是线程 - 安全。
如图所示,contrentMap用于缓存。关键值是格式,时区和语言环境(上下文)是相同的键。
1.不要将其定义为静态变量,请使用局部变量
2.锁定:同步锁和锁锁
3.使用ThreadLocal方法
4.使用DateTimeFormatter而不是SimpleDateFormat(DateTimeFormatter是线程-Safe,Java 8+支持)
5.使用FastDateFormat替换SimpleDateFormat(FastDateFormat是线程-Safe,Apache Commons Lang支持,Java8之前建议使用此用法)
本文分享了华为云社区的诚意,作者:xiaowuzhu。