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

标签 java.util.logging

在用于格式化调试日志的抽象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/

    相关文章:

    java - 在 logging.properties 中自定义日志格式

    java - 如何调节日志指令随时间产生的打印输出量?

    java - 如何在项目中包含多个 log4j2.xml 文件?

    使用日志记录 API 进行 Java 条件日志记录

    java util 记录多个处理程序导致重复的日志消息

    java - 如何完全禁用 JAudioTagger 记录器

    jakarta-ee - 在 glassfish 中安装日志格式化程序

    java - 以编程方式关闭 Jersey 日志记录

    java - 每次需要时都使用 Logger.getLogger() 或每个类(class)创建一次

    java - 以编程方式配置记录器