FindBugsで"static な java.text.DateFormat のメソッドを呼び出しています。"が警告される件
まあ、日本語を読んだだけでは意味が分からなくて、色々ググってたら以下を見つけた。
Call to method of static java.text.DateFormat not advisable? - Stack Overflow
つまり、java.text.DateFormatはスレッドセーフじゃないのに、staticなメソッドから呼んじゃってるよってことらしい。
java.text.DateFormatはスレッドセーフじゃないって言われてるけど、スレッドセーフじゃなかったらどうなるの?
と思い、サンプルコードを書いてみた。
import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; public class Main { private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd"); private static final int NUM_THREAD = 100; public static void main(String[] args) { for(int i=0; i<NUM_THREAD; i++) { new Thread(new Runnable() { //private final SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd"); public void run() { for(int i=0; i<10000; i++) { for(int j=1; j<=9; j++) { try { String strDate = "2012060" + j; Date date = sdf.parse(strDate); if(j != date.getDate()) { System.err.println("strDate = " + strDate + ", date = " + date); } } catch(ParseException e) { e.printStackTrace(); } } } } }).start(); } } }
NUM_THREADが1のときは問題は起きないけど、100とかにすると、たちまち元の日付と違う日付にパースされたり、ひどいときには、空文字をパースしようとしてParseExceptionが発生したり色々。
スレッド単位のインスタンスにすれば、当然問題は起きず。
なんでスレッドセーフじゃないのかってのを調べようと思ってソースも読んでみた。
SimpleDateFormat にまつわるぐだぐだ話。 - kameidの備忘録 - Sharpen the Saw!
たぶん、ここに書いてある通り。インスタンス変数書き換えまくってるから。
それはそれでいいとして、java.text.DateFormat.javaの先頭のコメント欄。
Oracleとか、IBMとかはさておき、Taligentとはなんぞや?さっそくググる。
Taligent - Wikipedia
Taligent(タリジェント)は、1992年にアップルコンピュータとIBMが共同で設立した会社、およびその会社の開発していたオブジェクト指向の次世代オペレーティングシステムの名称である[1][2][3]。これは1991年のIBMとアップルの包括的提携の実現化の1つ[4]で、1994年にはヒューレット・パッカードも資本参加した[5]。
・・・
1996年にタリジェントはIBMに吸収され、プロジェクトは中止された[8][9]。IBMはCommonPointを1997年に販売終了した[10]。タリジェントの開発していたフレームワークの一部は、IBMオープンクラスライブラリ(IOCL)や、JDK (Java Development Kit)の国際化対応部分などに引き継がれた。
へー!と思わず思った。
あのアップルがねえ、と思ったけど、今これ書いてて、アップルのいつの時期だろう?と思って、またググってみた。
アップル インコーポレイテッド - Wikipedia
どうもこれみると、アップルの低迷期だったようです。。納得。
というわけで、思わぬところから、思わぬ歴史まで知ることができたのでした。