为什么 java.util.logging.Formatter 中的 formatMessage() 方法是同步的?
Why is the formatMessage() method in java.util.logging.Formatter synchronized?
抽象的JDK class Formatter,用于格式化调试日志,formatMessage方法被声明为synchronized。
但是,我无法确定为什么会这样。
显然,可以编写非线程安全的覆盖版本,但我想知道为什么默认实现不是线程安全的。
[T]he formatMessage method is declared as synchronized.However, I haven't been able to determine why that is the case.
java.util.logging.Formatter 的早期版本试图缓存资源包获取字符串调用的结果以避免构建 java.util.MissingResourceException
。同步用于保护用于缓存查找的 HashMap
。
这里是 Copyright 2004 Sun Microsystems, Inc. version 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;
}
}
I'm wondering why the default implementation is not thread safe.
当缓存代码被注释掉时,同步应该被删除。此问题在 JDK-8153666: Possible optimization of Formatter.formatMessage.
下归档
It's definitely synchronized in OpenJDK but perhaps not in the JavaDocs
Remove "synchronized" and "native" from signatures. Javadoc generates an API specification. These two keywords do not belong in the signatures of a specification, because they are implementation-specific. The keyword "native" does not need to be documented. The keyword "synchronized" indicates thread-safe behavior that should instead be described in the method descriptions. A thread-safe method itself might not use the "synchronized" keyword but might call private methods that are.
P.S.
record.essage
是原始代码中的实际错字。
- 注意
record.getMessage()
如何调用多次,即使它在第一次调用时存储在本地。
- 该代码允许将空引用传递给
catalog.getString
,这将因 NPE 而失败。
抽象的JDK class Formatter,用于格式化调试日志,formatMessage方法被声明为synchronized。
但是,我无法确定为什么会这样。
显然,可以编写非线程安全的覆盖版本,但我想知道为什么默认实现不是线程安全的。
[T]he formatMessage method is declared as synchronized.However, I haven't been able to determine why that is the case.
java.util.logging.Formatter 的早期版本试图缓存资源包获取字符串调用的结果以避免构建 java.util.MissingResourceException
。同步用于保护用于缓存查找的 HashMap
。
这里是 Copyright 2004 Sun Microsystems, Inc. version 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;
}
}
I'm wondering why the default implementation is not thread safe.
当缓存代码被注释掉时,同步应该被删除。此问题在 JDK-8153666: Possible optimization of Formatter.formatMessage.
下归档It's definitely synchronized in OpenJDK but perhaps not in the JavaDocs
Remove "synchronized" and "native" from signatures. Javadoc generates an API specification. These two keywords do not belong in the signatures of a specification, because they are implementation-specific. The keyword "native" does not need to be documented. The keyword "synchronized" indicates thread-safe behavior that should instead be described in the method descriptions. A thread-safe method itself might not use the "synchronized" keyword but might call private methods that are.
P.S.
record.essage
是原始代码中的实际错字。- 注意
record.getMessage()
如何调用多次,即使它在第一次调用时存储在本地。 - 该代码允许将空引用传递给
catalog.getString
,这将因 NPE 而失败。