SimpleDateFormat--容易发生线程安全的类

在java中,可以使用 SimpleDateFormat 日期格式化类来对日期或者时间进行格式化,但在多线程环境下使用要注意线程安全问题。以下代码都是基于JDK1.8

 * <p>
 * Date formats are not synchronized.
 * It is recommended to create separate format instances for each thread.
 * If multiple threads access a format concurrently, it must be synchronized
 * externally.

public class SimpleDateFormat extends DateFormat {

源码文件中已经注明此类是线程不安全,使用过程中应当注意。
并发问题主要发生在SimpleDateFormat 的format 方法, calendar.setTime(date);这一句。

 // Called from Format after creating a FieldDelegate
    private StringBuffer format(Date date, StringBuffer toAppendTo,
                                FieldDelegate delegate) {
        // Convert input date to time field list
        calendar.setTime(date);

        boolean useDateFormatSymbols = useDateFormatSymbols();

format方法中这个calendar是一个成员变量,如果A线程先设置了dateA值,执行到下一步,
然后B线程又将这个calendar变量设置为dateB值,那么A线程后面获取到的calendar值将
会是dateB值,而不是一开始设置的dateA值。要解决这个问题,可以使用ThreadLocal类解决并发问题。

private static final ThreadLocal<DateFormat> ymdhmsFormat = ThreadLocal.withInitial(() ->
        new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
);

然后通过 ymdhmsFormat.get() 获取到对应的DateFormat 实例对象。其中ThreadLocal主要是通过
一条线程对应一个DateFormat实例变量的方法来解决线程并发问题。即使多条线程同时访问format方法,
但是因为每一条线程都对应一个DateFormat实例对象,所以能安全执行format方法,而不是发生时间错乱问题。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容