0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【 Java 】SimpleDateFormatのスレッドセーフではない挙動を確認

Last updated at Posted at 2025-01-25

■ はじめに

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

◽️ 参考資料

※項目:「同期」参照

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?