SimpleDateFormat のスレッドセーフの謎。

ページによって記述が異なり、自分でソースを見てみると何回注意深く読んでも問題の無い使い方まで「バグる」とかかれていたりする SimpleDateFormat 関係の機能。


長い間もやもやしてた部分があったんだけど、以下の記述を見て疑問が解けた。

参考: AKIMOTO, HirokiさんのSimpleDateFormat はスレッドセーフではない
ちなみにここではDate#toString()も危ないと書いてあるが、もしかしてJDK1.3の話じゃなかろうか。
JDK1.4ではSimpleDateFormatを使う際にsynchronizedしてるから大丈夫なんじゃないかなぁ?
JDK1.5や1.6ではDateFormatを使わずStringBuilderを使って直接文字列を生成しているから大丈夫だろう。

Java日付処理メモ(Hishidama's Java Date Memo)

なるほど、新しいソースで確認してたから問題が発見できなかったのか・・・。


職場では、SimpleDateFormat.parse() は問題を起こすと言うので、腫れ物に触るような扱い、というか、「使用禁止」である。んでどうしてるかというと、各自でパース機能を実装している。うーん。それはそれで微妙・・・。


幾種類かの標準的なフォーマットでのパースに関しては共通ライブラリに用意されたのでそれを使えば良いとして、あんまり標準的じゃないパースをしたい場合はやっぱり SimpleDateFormat は便利だろう。


上記ページでもかかれてるが ThreadLocal で SimpleDateFormat のインスタンスを各スレッド用に一個用意するのが簡単な気がする。そういうユーティリティーを一個用意しておいて皆で使えばいいだろう。


ちなみに、JDK1.6 の JavaDoc にもこのようにかかれている。

同期

日付フォーマットは同期化されません。スレッドごとに別のフォーマットインスタンスを作成することをお勧めします。複数のスレッドがフォーマットに同時にアクセスする場合は、外部的に同期化する必要があります。

Oracle Technology Network for Java Developers | Oracle Technology Network | Oracle