在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方法,而不是发生时间错乱问题。
网友评论