在用于格式化调试日志的抽象JDK 类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
用于缓存查找。这是版权所有 2004 Sun Microsystems, Inc. 版本 1.16,2003 年 12 月 19 日的源代码,请注意注释:
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
来自 What's New in Javadoc 1.2 :
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.
附言
record.essage
是原始代码中的实际拼写错误。 record.getMessage()
多次调用,即使它在第一次调用时存储在本地。 catalog.getString
这将因 NPE 而失败。 关于java.util.logging - 为什么 java.util.logging.Formatter 中的 formatMessage() 方法是同步的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36433146/