线程安全日期格式化操作的几种方式
由于 DateFormat
是非线程安全的,因此在多线程并发情况下日期格式化时需要特别注意。下面记录几种格式化的方式:
线程不安全的处理方式
private static final DateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//线程不安全
这种方式会报如下异常:
java.lang.NumberFormatException: For input string: "" at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65) at java.lang.Long.parseLong(Long.java:601) at java.lang.Long.parseLong(Long.java:631) at java.text.DigitList.getLong(DigitList.java:195) at java.text.DecimalFormat.parse(DecimalFormat.java:2051) at java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:2162) at java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1514) at java.text.DateFormat.parse(DateFormat.java:364) at com.concurrent.DateUtils.parse(DateUtils.java:28) at com.concurrent.DateUtils$2.run(DateUtils.java:42) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) at java.lang.Thread.run(Thread.java:745)
线程安全的处理方式
方式一,每次new一个对象
public static Date parse(String date) throws ParseException { return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(date);}
方式二,通过ThreadLocal进行处理
private static final ThreadLocalLOCAL_DATE_FORMAT = new ThreadLocal (){ @Override protected DateFormat initialValue() { return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); } };
- 如果是JDK7及以下的应用,可用ThreadLocal的方式
方式三,java8 通过 DateTimeFormatter 进行处理
private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime dateTime = LocalDateTime.parse(date, DATE_TIME_FORMATTER);LOCAL_DATE_FORMAT.get().parse(date);
- 如果是JDK8的应用,可以使用instant代替Date,Localdatetime代替Calendar,Datetimeformatter代替Simpledateformatter,官方给出的解释:simple beautiful strong immutable thread-safe。