代码之家  ›  专栏  ›  技术社区  ›  Uri

是什么原因导致java.util.logging文件.格式化程序.formatMessage()已同步?[副本]

  •  0
  • Uri  · 技术社区  · 7 年前

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

    然而,我还不能确定为什么会这样。

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

    0 回复  |  直到 10 年前
        1
  •  4
  •   jmehrens    10 年前

    [T] formatMessage方法声明为同步。但是,我还不能确定为什么会这样。

    java.util.logging.Formatter 试图缓存资源束get string调用的结果,以避免构造 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 .

    What's New in Javadoc 1.2 :

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

    附笔。

    1. record.essage 是源代码中的实际输入错误。
    2. 注意怎么做 record.getMessage() 多次调用,即使它在第一次调用时存储在本地。
    3. catalog.getString NPE会失败。