SimpleDateFormatのスレッドセキュリティの問題と解決策について
詳細
まずSimpleDateFormatにスレッドセキュリティの問題がある理由を簡単に説明します.SimpleDateFormatはDateFormatクラスを継承し、クラスには保護されたタイプのCalendarオブジェクトがあります.SimpleDateFormatのformatメソッドを見てみましょう.
赤い行のコードを見ると、formatメソッドがスレッドではなく安全である理由がわかると思います.複数のスレッドがSimpleDateFormatインスタンスを共有する場合、Calendarオブジェクトへの変更は相互に影響し、スレッドセキュリティの問題が発生します.
OK、ソリューション:
1、使用するたびにSimpleDateFormatのインスタンスを作成しますが、パフォーマンスは低下します(現在のjdkの優れたパフォーマンスとソフト・ハードウェアのパフォーマンスの向上で、SimpleDateFormatインスタンスの作成がパフォーマンスに与える影響は明らかではありません).
2、ThreadLocalを使用してマルチスレッド共有インスタンスを回避し、コード:
3、synchronizedやサードパーティ製ツールクラスを使用するなど、他の方法があります.前者は性能に大きな影響を及ぼし、後者は本稿の議論の範囲内ではありません.皆さんは自分で研究する時間があります.
まずSimpleDateFormatにスレッドセキュリティの問題がある理由を簡単に説明します.SimpleDateFormatはDateFormatクラスを継承し、クラスには保護されたタイプのCalendarオブジェクトがあります.SimpleDateFormatのformatメソッドを見てみましょう.
private StringBuffer format(Date date, StringBuffer toAppendTo,
FieldDelegate delegate) {
// Convert input date to time field list
calendar.setTime(date);
boolean useDateFormatSymbols = useDateFormatSymbols();
for (int i = 0; i < compiledPattern.length; ) {
int tag = compiledPattern[i] >>> 8;
int count = compiledPattern[i++] & 0xff;
if (count == 255) {
count = compiledPattern[i++] << 16;
count |= compiledPattern[i++];
}
......
}
赤い行のコードを見ると、formatメソッドがスレッドではなく安全である理由がわかると思います.複数のスレッドがSimpleDateFormatインスタンスを共有する場合、Calendarオブジェクトへの変更は相互に影響し、スレッドセキュリティの問題が発生します.
OK、ソリューション:
1、使用するたびにSimpleDateFormatのインスタンスを作成しますが、パフォーマンスは低下します(現在のjdkの優れたパフォーマンスとソフト・ハードウェアのパフォーマンスの向上で、SimpleDateFormatインスタンスの作成がパフォーマンスに与える影響は明らかではありません).
2、ThreadLocalを使用してマルチスレッド共有インスタンスを回避し、コード:
public class ConcurrentDateUtil {
private static ThreadLocal DateThreadLocal = new ThreadLocal() {
protected DateFormat initialValue() {
return new SimpleDateFormat("yyyy-MM-dd");
}
};
private static ThreadLocal DateTimeThreadLocal = new ThreadLocal() {
protected DateFormat initialValue() {
return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
}
};
public static Date parseDate(String dateStr) throws ParseException {
return DateThreadLocal.get().parse(dateStr);
}
public static String formatDate(Date date) {
return DateThreadLocal.get().format(date);
}
public static Date parseDateTime(String dateStr) throws ParseException {
return DateTimeThreadLocal.get().parse(dateStr);
}
public static String formatDateTime(Date date) {
return DateTimeThreadLocal.get().format(date);
}
}
3、synchronizedやサードパーティ製ツールクラスを使用するなど、他の方法があります.前者は性能に大きな影響を及ぼし、後者は本稿の議論の範囲内ではありません.皆さんは自分で研究する時間があります.