■ はじめに
Java勉強につき、メモを残します。
下記内容は、備忘録レベルで書いてますので間違い等あるかもしれません。
参考にする際にはその点ご認識のほどお願いします。。
■ SimpleDateFormatとは
日付をフォーマットしたり解析したりする際に使用されるクラスです。
Data型の日付(例:2025-01-01)をformatメソッドを使用して、String型にフォーマットしたり、String型の日付をparseメソッドで解析してDate型を生成したりなどです。
このSimpleDateFormatはスレッドセーフではないので、マルチスレッドで動かした際に
予期せぬ値を返したり、例外が出るため、Java8以降では使用を控えた方が良いです。
代替として、DateTimeFormatterクラスがスレッドセーフのクラスになるため、
フォーマットや解析にはこちらのクラスを使用することを推奨します。
今回は、SimpleDateFormatをマルチスレッドで動かしてみて確認しました。
私は参考資料の文字だけ見ても理解できなかったので、私と同じようにイメージがしずらい方は、下記を参考にしてみてください。
※DateTimeFormatterクラスの説明は今回しません。。
※下記ソースで使用しているDateクラスもJava8では非推奨メソッドが多いため、新しく追加されたLocalDateクラスなどを使用する方が良いです。
■ 検証ソース
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class SimpleDateFormatTest {
public static void main(String[] args) {
// newでSimpleDateFormatをインスタンス化しフォーマットを用意
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// Calendarクラスを使用し、Date型の2025-01-01 09:00:00を作成
Calendar calendar = Calendar.getInstance();
calendar.set(2025, Calendar.JANUARY,25,9,0,0);
Date date = calendar.getTime();
// フォーマットを使用して取得したい期待値
String kitaichi = "2025-01-25 09:00:00";
// スレッドを10個作成し、複数のスレッドでsimpleDateFormat変数を使用
ExecutorService executor = Executors.newFixedThreadPool(10);
for (int i = 0; i < 100; i++) {
executor.submit(() -> {
// Date型からString型に変換
String sdf = simpleDateFormat.format(date);
try {
// SimpleDateFormatはスレッドセーフでなく内部的に値を保持しているため
// 複数のスレッドで引数の値を操作する処理際に、予期せぬ値に変わってしまう
Date result = simpleDateFormat.parse(sdf);
} catch (ParseException e) {
System.out.println("例外発生: " + e);
}
if (!kitaichi.equals(sdf)) {
System.out.println("不整合: " + kitaichi + " : " + sdf);
}
});
}
}
}
出力結果の左側の「2025-01-25 09:00:00」はString型で定義したkitaichi変数です。
右側がformatした値ですが、年月日や分秒が期待値とは全く違う値になっていることが確認できます。
不整合: 2025-01-25 09:00:00 : 2024-01-31 09:20:00
不整合: 2025-01-25 09:00:00 : 2107-06-29 09:00:00
不整合: 2025-01-25 09:00:00 : 2025-01-25 09:00:20
不整合: 2025-01-25 09:00:00 : 2024-12-31 09:00:00
◽️ 参考資料
※項目:「同期」参照