DateFormatマルチスレッドを安全にする
「DateFormatは同期されていません。スレッドごとに独自のフォーマット例を作成することを推奨します。複数のスレッドが同時にフォーマットにアクセスする場合、外部同期を維持しなければなりません。」 まず簡単な方法を見せてください。
この方法は、「2010101」のような形をした文字列をDateタイプに変換することである。同時に方法はマルチスレッドの同時アクセスをサポートしていますが、これはコストがかかります。この方法の呼び出しごとにSimpleDateFormatオブジェクトを作成します。
とても自然な私達は以下の改善を思い付いて、SimpleDateFormatを静的な大域変数として宣言します。
また、マルチスレッドの同期を確保するためには、ロックをかける必要があります。
このような最適化はまだ不十分であり,マルチスレッド競合の場合は性能が良くないからである。すべてのスレッドには自分のDateFormatがある方がいいです。これは争いも起こらないし、各スレッドに対しては一つのDateFormatオブジェクトだけを作成します。 ThreadLocalはちょうどこの需要を満たすことができます。ここでは多く説明をしません。
上にはまた、異なるPatternに対するThreadLocalのキャッシュが追加されています。このように各スレッドに対して、各patternはSimpleDateFormatオブジェクトを作成するだけで、マルチスレッドアクセスは競合しません。 コードはまだ多くの改善すべきところがあります。不法なpatternに対してキャッシュしないでください。もっと速く、もっとメモリを節約する方法がありますか? 急いで、間違いがあったら教えてください。
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に対してキャッシュしないでください。もっと速く、もっとメモリを節約する方法がありますか? 急いで、間違いがあったら教えてください。