DateFormatマルチスレッドを安全にする


「DateFormatは同期されていません。スレッドごとに独自のフォーマット例を作成することを推奨します。複数のスレッドが同時にフォーマットにアクセスする場合、外部同期を維持しなければなりません。」 まず簡単な方法を見せてください。 
public static Date toDate(String dateStr) {
SimpleDateFormat p= new SimpleDateFormat("yyyyMMdd");
try{
    return p.parse(dateStr);
}catch (ParseException e) {
}
return null;
}
 
この方法は、「2010101」のような形をした文字列をDateタイプに変換することである。同時に方法はマルチスレッドの同時アクセスをサポートしていますが、これはコストがかかります。この方法の呼び出しごとにSimpleDateFormatオブジェクトを作成します。 
とても自然な私達は以下の改善を思い付いて、SimpleDateFormatを静的な大域変数として宣言します。 
 
private static final SimpleDateFormat PATTERN = new SimpleDateFormat("yyyyMMdd");
 
また、マルチスレッドの同期を確保するためには、ロックをかける必要があります。 
 
public synchronied static Date toDate(String dateStr) {
try{
return PATTERN.parse(dateStr);
}catch (ParseException e) {
}
return null;
}
 
このような最適化はまだ不十分であり,マルチスレッド競合の場合は性能が良くないからである。すべてのスレッドには自分のDateFormatがある方がいいです。これは争いも起こらないし、各スレッドに対しては一つのDateFormatオブジェクトだけを作成します。 ThreadLocalはちょうどこの需要を満たすことができます。ここでは多く説明をしません。 
import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.Map;

public class DateFormatFactory {
	private static final Map<String, ThreadLocal<SimpleDateFormat>> pool = new HashMap<String, ThreadLocal<SimpleDateFormat>>();
	private static final Object lock = new Object();

	public static SimpleDateFormat getDateFormat(String pattern) {
		ThreadLocal<SimpleDateFormat> tl = pool.get(pattern);
		if (tl == null) {
			synchronized (lock) {
				tl = pool.get(pattern);
				if (tl == null) {
					final String p = pattern;
					tl = new ThreadLocal<SimpleDateFormat>() {
						protected synchronized SimpleDateFormat initialValue() {
							return new SimpleDateFormat(p);
						}
					};
					pool.put(p, tl);
				}
			}
		}
		return tl.get();
	}
}

public static Date toDate(String dateStr,String pattern) {
try{
return getDateFormat(pattern).parse(dateStr);
}catch (ParseException e) {
}
return null;
}
 
上にはまた、異なるPatternに対するThreadLocalのキャッシュが追加されています。このように各スレッドに対して、各patternはSimpleDateFormatオブジェクトを作成するだけで、マルチスレッドアクセスは競合しません。 コードはまだ多くの改善すべきところがあります。不法なpatternに対してキャッシュしないでください。もっと速く、もっとメモリを節約する方法がありますか? 急いで、間違いがあったら教えてください。