LoginSignup
7
7

More than 5 years have passed since last update.

SimpleDateFormatはスレッドセーフではない

Posted at

タイトルの通りSimpleDateFormatはスレッドセーフではないことを確認してみた。
反対にDateTimeFormatterはスレッドセーフとのことなので書き方の違いも合わせて比較してみた。

サンプルコード

マルチスレッドでの実行を想定して以下のコードを実行してみる。

import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Calendar;

/**
 * {@link SimpleDateFormat}と{@link DateTimeFormatter}の比較
 */
public class CompareSample {

    private static final SimpleDateFormat SIMPLE_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd");
    private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ISO_DATE;

    public void execute() {
        Thread t1 = new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                String sdf = this.useSimpleDateFormat(2016, 11, 7);
                String dtf = this.useDateTimeFormatter(2016, 11, 7);
                System.out.println("SimpleDateFormat=" + sdf + ", DateTimeFormatter=" + dtf + ", equals=" + sdf.equals(dtf));
            }
        });

        Thread t2 = new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                String sdf = this.useSimpleDateFormat(2017, 12, 17);
                String dtf = this.useDateTimeFormatter(2017, 12, 17);
                System.out.println("SimpleDateFormat=" + sdf + ", DateTimeFormatter=" + dtf + ", equals=" + sdf.equals(dtf));
            }
        });

        t1.start();
        t2.start();
    }

    private String useSimpleDateFormat(int year, int month, int date) {
        Calendar cal = Calendar.getInstance();
        cal.set(year, month - 1, date);
        return SIMPLE_DATE_FORMAT.format(cal.getTime());

    }

    private String useDateTimeFormatter(int year, int month, int date) {
        LocalDate localDate = LocalDate.of(year, month, date);
        return DATE_TIME_FORMATTER.format(localDate);
    }
}
import org.junit.Test;

/**
 * {@link CompareSample}のテスト
 */
public class CompareSampleTest {

    @Test
    public void testExecute() {
        CompareSample test = new CompareSample();
        test.execute();
    }

}

実行結果

どちらも「2016-11-07」または「2017-12-17」であればOKだが、
SimpleDateFormatはたまにおかしな値を返すことがわかる。

SimpleDateFormat=2017-12-17, DateTimeFormatter=2017-12-17, equals=true
SimpleDateFormat=2016-11-07, DateTimeFormatter=2016-11-07, equals=true
SimpleDateFormat=2016-11-07, DateTimeFormatter=2016-11-07, equals=true
SimpleDateFormat=2017-11-07, DateTimeFormatter=2017-12-17, equals=false
SimpleDateFormat=2016-11-17, DateTimeFormatter=2016-11-07, equals=false
SimpleDateFormat=2017-12-17, DateTimeFormatter=2017-12-17, equals=true
SimpleDateFormat=2016-11-17, DateTimeFormatter=2016-11-07, equals=false
SimpleDateFormat=2017-12-17, DateTimeFormatter=2017-12-17, equals=true
SimpleDateFormat=2017-12-17, DateTimeFormatter=2017-12-17, equals=true
SimpleDateFormat=2016-11-17, DateTimeFormatter=2016-11-07, equals=false
SimpleDateFormat=2017-12-17, DateTimeFormatter=2017-12-17, equals=true
SimpleDateFormat=2016-11-07, DateTimeFormatter=2016-11-07, equals=true
SimpleDateFormat=2016-11-07, DateTimeFormatter=2016-11-07, equals=true
SimpleDateFormat=2017-12-17, DateTimeFormatter=2017-12-17, equals=true
SimpleDateFormat=2016-11-07, DateTimeFormatter=2016-11-07, equals=true
SimpleDateFormat=2017-12-17, DateTimeFormatter=2017-12-17, equals=true
SimpleDateFormat=2016-11-07, DateTimeFormatter=2016-11-07, equals=true
SimpleDateFormat=2017-12-17, DateTimeFormatter=2017-12-17, equals=true
SimpleDateFormat=2016-11-07, DateTimeFormatter=2016-11-07, equals=true
SimpleDateFormat=2017-12-17, DateTimeFormatter=2017-12-17, equals=true
7
7
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
7
7