Java爬坑 之 SimpleDateFormat 时间转换异常
前言
SimpleDateFormat 一个今本上天天在用的 Java类,但是使用不当会出现莫名的错误,如:抛异常、转换结果错误等;
因为 SimpleDateFormat 和 DateFormat 类都是线程不安全的,所以不能使用工具类直接创建静态实例,平常开发环境 并发较少体现不出问题,一旦上正式出现多线程、高并发、负载的情况下就会出现
解决办法
每次使用创建新实例
每次创建新实例会将对象变为局部变量从而解决问题,但是也会创建很多对象,但是一般来说可以忽略
public class DateUtil {
public static String formatDate(Date date)throws ParseException{
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
return sdf.format(date);
}
public static Date parse(String strDate) throws ParseException{
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
return sdf.parse(strDate);
}
}
使用同步锁 synchronized
多线程调用会出现线程等待 阻塞 ,会对高并发造成一定的影响
public class DateUtil {
private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
public static String formatDate(Date date)throws ParseException{
synchronized(sdf){
return sdf.format(date);
}
}
public static Date parse(String strDate) throws ParseException{
synchronized(sdf){
return sdf.parse(strDate);
}
}
}
使用ThreadLocal
ThreadLocal 是线程的局部变量,是每一个线程所单独持有的,其他线程不能对其进行访问,由于在每个线程中都创建了副本,所以要考虑它对资源的消耗
- 重写 initialValue 方法
public class DateUtil {
private static ThreadLocal<DateFormat> threadLocal = new ThreadLocal<DateFormat>() {
protected DateFormat initialValue() {
return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
}
};
public static Date parse(String dateStr) throws ParseException {
return threadLocal.get().parse(dateStr);
}
public static String format(Date date) {
return threadLocal.get().format(date);
}
}
- 调用 set() 方法赋值
public class DateUtil {
private static ThreadLocal<DateFormat> threadLocal = new ThreadLocal<DateFormat>();
public static DateFormat getDateFormat()
{
DateFormat df = threadLocal.get();
if(df==null){
df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
threadLocal.set(df);
}
return df;
}
public static String formatDate(Date date) throws ParseException {
return getDateFormat().format(date);
}
public static Date parse(String strDate) throws ParseException {
return getDateFormat().parse(strDate);
}
}
使用说明
方法一二 虽对耗资源,但都是微乎其微的基本可以满足日常需求;方法三 对性能有极致的要求的可以用 ThreadLocal
版权声明:本文为原创文章,版权归本站所有,欢迎分享本文,转载请保留出处!