デバッグログのフォーマットに使用される抽象JDKクラスFormatterでは、formatMessageメソッドがsynchronizedとして宣言されています。java.util.logging.FormatterのformatMessage()メソッドが同期されているのはなぜですか?
しかし、私はそのような場合の理由を特定できませんでした。
明らかに、スレッドセーフではないオーバーライドバージョンを書くことができますが、なぜデフォルトの実装がスレッドセーフではないのだろうと思います。
デバッグログのフォーマットに使用される抽象JDKクラスFormatterでは、formatMessageメソッドがsynchronizedとして宣言されています。java.util.logging.FormatterのformatMessage()メソッドが同期されているのはなぜですか?
しかし、私はそのような場合の理由を特定できませんでした。
明らかに、スレッドセーフではないオーバーライドバージョンを書くことができますが、なぜデフォルトの実装がスレッドセーフではないのだろうと思います。
[T] formatMessageメソッドはsynchronizedとして宣言されていますが、私はそのような理由を判断できませんでした。
java.util.logging.Formatterの初期バージョンは、java.util.MissingResourceException
の構築を避けるために、リソースバンドルのget string呼び出しの結果をキャッシュしようとしました。ルックアップのキャッシュに使用されたHashMap
を保護するために同期が使用されました。ここで
は、著作権2004年サン・マイクロシステムズ社のバージョン1.16で、12/19/03ソースコード、コメントの点に注意してください。
public synchronized String formatMessage(LogRecord record) {
String format = record.getMessage();
java.util.ResourceBundle catalog = record.getResourceBundle();
if (catalog != null) {
// We cache catalog lookups. This is mostly to avoid the
// cost of exceptions for keys that are not in the catalog.
// if (catalogCache == null) {
// catalogCache = new HashMap();
// }
// format = (String)catalogCache.get(record.essage);
// if (format == null) {
try {
format = catalog.getString(record.getMessage());
} catch (java.util.MissingResourceException ex) {
// Drop through. Use record message as format
format = record.getMessage();
}
// catalogCache.put(record.message, format);
// }
}
// Do the formatting.
try {
Object parameters[] = record.getParameters();
if (parameters == null || parameters.length == 0) {
// No parameters. Just return format string.
return format;
}
// Is is a java.text style format?
// Ideally we could match with
// Pattern.compile("\\{\\d").matcher(format).find())
// However the cost is 14% higher, so we cheaply check for
// 1 of the first 4 parameters
if (format.indexOf("{0") >= 0 || format.indexOf("{1") >=0 ||
format.indexOf("{2") >=0|| format.indexOf("{3") >=0) {
return java.text.MessageFormat.format(format, parameters);
}
return format;
} catch (Exception ex) {
// Formatting failed: use localized format string.
return format;
}
}
デフォルトの実装では、スレッドセーフではありませんなぜ私は思ったんだけど。
キャッシュコードがコメントアウトされたときに、同期が削除されているはずです。この問題はJDK-8153666: Possible optimization of Formatter.formatMessageの下に提出されています。
それは間違いなくWhat's New in Javadoc 1.2からのJavaDoc
でのOpenJDKに同期しますが、おそらくないです:
削除 "同期" と署名から "ネイティブ"。 JavadocはAPI仕様を生成します。これらの2つのキーワードは、実装固有のものであるため、仕様のシグネチャには属しません。キーワード「native」は文書化する必要はありません。キーワード "synchronized"は、スレッドセーフな動作を示し、代わりにメソッドの説明に記述する必要があります。スレッドセーフメソッド自体は "synchronized"キーワードを使用しないかもしれませんが、プライベートメソッドを呼び出すかもしれません。
P.S.
record.essage
元のコードからの実際の入力ミスです。record.getMessage()
が最初の呼び出しでローカルに格納されていても、複数回呼び出されたことに注目してください。catalog.getString
にヌル参照を渡すことができます。
https://docs.oracle.com/javase/7/docs/api/java/util/logging/Formatter.html#formatMessage(java.util.logging.LogRecord)私はそれを表示しません同期されていなくても、7も8でもない。 –
OpenJDKでは間違いなく同期化されているが、おそらくJavaDocs(独特のもの) にはない。http://grepcode.com/file/repository.grepcode.com/java/root/jdk/ openjdk/6-b14/java/util/logging/Formatter。java#113 – Uri
おそらく、たくさんのリソースバンドルを読み込んでメモリを奪うのを避けるために?その仕様に関する直接の詳細はありません。 –