SimpleDateFormat高并发情况下报错问题:
SimpleDateFormat经常被声明为static,在并发环境下公用一个实例,由于它不是线程安全的会产生两种问题:1.日期并不是预想的日期,乱七八糟的任何日期都可能出现。 2. 一定几率下抛异常。
所以有人就每次调用格式化都重新new一个SimpleDateFormat实例,这种方式会存在性能问题,因为其实例化是“expensive”的。所以最优的解决方案是采用ThreadLocal方式。
/**
-
时间工具类
*/
public class TimeUtil {public static final String YEAR_MONTH_DAY_SECOND = “yyyy-MM-dd HH:mm:ss”;
public static final String YEAR_MONTH_DAY_SECOND2 = “yyyy/MM/dd HH:mm:ss”;
public static final String YEAR_MONTH_DAY_SECOND3 = “yyyy年MM月dd日 HH时mm分ss秒”;
public static final String YEAR_MONTH_DAY = “yyyy-MM-dd”;
public static final String YEAR_MONTH_DAY2 = “yyyy年MM月dd日”;/**
- 采用 ThreadLocal 避免 SimpleDateFormat 非线程安全的问题
-
- Key —— 时间格式
- Value —— 解析特定时间格式的 SimpleDateFormat
*/
private static ThreadLocal<Map<String, SimpleDateFormat>> sThreadLocal = new ThreadLocal<>();
/**
-
获取解析特定时间格式的 SimpleDateFormat
-
@param pattern 时间格式
*/
private static SimpleDateFormat getDateFormat(String pattern) {
Map<String, SimpleDateFormat> strDateFormatMap = sThreadLocal.get();if (strDateFormatMap == null) {
strDateFormatMap = new HashMap<>();
}SimpleDateFormat simpleDateFormat = strDateFormatMap.get(pattern);
if (simpleDateFormat == null) {
simpleDateFormat = new SimpleDateFormat(pattern, Locale.getDefault());
strDateFormatMap.put(pattern, simpleDateFormat);
sThreadLocal.put(strDateFormatMap);
}return simpleDateFormat;
}
/**
-
时间格式化
-
@param date:要格式化的时间
-
@param pattern:要格式化的类型
*/
public static String formatDate(Date date, String pattern) {
if (date == null || pattern == null) {
return null;
}return getDateFormat(pattern).format(date);
}
}