线程安全问题解决方案"/>
SimpleDateFormat日期转换之线程安全问题解决方案
java 日期转换,线程安全问题
java.text.SimpleDateFormat,是线程非安全,原因在于SimpleDateFormat中,使用到了Calendar类对象,在执行parse() 和format()方法时,调用calendar.setTime(date)方法。那么问题来了:多线程环境下,线程非安全。
解决方案:
1)每次使用,都创建新实例;
2)使用三方类库。
package com.time;import org.apachemons.lang.time.DateFormatUtils;
import org.apachemons.lang.time.DateUtils;
import org.apachemons.lang.time.FastDateFormat;import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;/*** Created by Liuxd on 2018-08-28.*/
public class TestTime {private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");private static final FastDateFormat timeFormat = FastDateFormat.getInstance("yyyy-MM-dd");private static final SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");public static void TestDateTimeFormatter(ExecutorService pool) {for (int i = 0; i < 100000; i++) {Date date = DateUtils.addDays(new Date(), i);pool.execute(new Thread() {@Overridepublic void run() {String dateStr = DateFormatUtils.format(date, "yyyy-MM-dd");LocalDate localDate = LocalDate.parse(dateStr, formatter);String dateAfter = formatter.format(localDate);System.out.println(dateStr + " " + dateAfter);if (!dateStr.equals(formatter.format(localDate))) {System.out.println(dateStr + " " + dateAfter + " 发生异常情况");}}});}}public static void TestFastDateFormat(ExecutorService pool) {for (int i = 0; i < 100000; i++) {Date date = DateUtils.addDays(new Date(), i);pool.execute(new Thread() {@Overridepublic void run() {String dateStr = DateFormatUtils.format(date, "yyyy-MM-dd");String dateAfter = timeFormat.format(date);System.out.println(dateStr + " " + dateAfter);if (!dateStr.equals(dateAfter)) {System.out.println(dateStr + " " + dateAfter + " 发生异常情况");}}});}}/*** 会发生异常情况的日期转换* @param pool*/public static void TestSimpleDateFormat(ExecutorService pool) {for (int i = 0; i < 100000; i++) {Date date = DateUtils.addDays(new Date(), i);pool.execute(new Thread() {@Overridepublic void run() {String dateStr = DateFormatUtils.format(date, "yyyy-MM-dd");/*** SimpleDateFormat 对象,每次使用都使用新实例*/
// SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");String dateAfter = simpleDateFormat.format(date);System.out.println(dateStr + " " + dateAfter);if (!dateStr.equals(dateAfter)) {System.out.println(dateStr + " " + dateAfter + " 发生异常情况");}}});}}public static void TestDateFormatUtils(ExecutorService pool) {for (int i = 0; i < 100000; i++) {Date date = DateUtils.addDays(new Date(), i);pool.execute(new Thread() {@Overridepublic void run() {String dateStr = DateFormatUtils.format(date, "yyyy-MM-dd");String dateAfter = DateFormatUtils.format(date, "yyyy-MM-dd");System.out.println(dateStr + " " + dateAfter);if (!dateStr.equals(dateAfter)) {System.out.println(dateStr + " " + dateAfter + " 发生异常情况");}}});}}public static void main(String[] args) {ExecutorService pool = Executors.newFixedThreadPool(1000);
// TestDateTimeFormatter(pool);
// TestFastDateFormat(pool);TestSimpleDateFormat(pool);
// TestDateFormatUtils(pool);}}
3)ThreadLocal是使用空间换时间
使用ThreadLocal解决线程安全:
public class ThreadLocalDateUtil {private static final String date_format = "yyyy-MM-dd HH:mm:ss";private static ThreadLocal<DateFormat> threadLocal = new ThreadLocal<DateFormat>();public static DateFormat getDateFormat() { DateFormat df = threadLocal.get(); if(df==null){ df = new SimpleDateFormat(date_format); 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);} }
4)synchronized是使用时间换空间
public class DateSyncUtil {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);}}
}
其中3和4代码参考:
.html
更多推荐
SimpleDateFormat日期转换之线程安全问题解决方案
发布评论