为什么java.util.logging.Formatter中的formatMessage()方法已同步?

时间:2016-04-05 17:26:49

标签: java.util.logging

在抽象的JDK类Formatter中,用于格式化调试日志,formatMessage方法被声明为synchronized。

但是,我无法确定原因。

显然,可以编写非线程安全的覆盖版本,但我想知道为什么默认实现不是线程安全的。

1 个答案:

答案 0 :(得分:4)

  

[T]他将formatMessage方法声明为synchronized.However,我无法确定为什么会这样。

早期版本的java.util.logging.Formatter尝试缓存资源包获取字符串调用的结果,以避免构造java.util.MissingResourceException。同步用于保护用于缓存查找的HashMap

这是版权所有2004 Sun Microsystems,Inc。版本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下提交。

  

它确实在OpenJDK中同步,但可能不在JavaDocs

来自What's New in Javadoc 1.2

  

从签名中删除“synchronized”和“native”。 Javadoc生成API规范。这两个关键字不属于规范的签名,因为它们是特定于实现的。关键字“native”不需要记录。关键字“synchronized”表示应该在方法描述中描述的线程安全行为。线程安全方法本身可能不使用“synchronized”关键字,但可能会调用私有方法。

P.S。

  1. record.essage是原始代码中的实际拼写错误。
  2. 注意record.getMessage()多次调用多次,即使它在第一次调用时存储在本地。
  3. 该代码允许将空引用传递给catalog.getString,这将导致NPE失败。