我正在使用java logger类来记录一些东西,根据某些数据,我需要将日志配置为某些路由。

假设我有以下代码:

public class LoggerLocator {
  private static HashMap<String, Logger> loggerMap = new HashMap<String, Logger>();
  private static int count = 0;

  public Logger getLogger(String id) {
    if(!LoggerLocator.loggerMap.containsKey(id)) {
      configure(id);
    }
    return LoggerLocator.loggerMap.get(id);
  }

  private void configure(String id) {
    Logger logger = Logger.getLogger(LoggerLocator.class.getName());
    FileHandler fh = new FileHandler(String.format("/home/abc/logs/mylog_%d.log", id), true);
    fileHandler.setFormatter(new MyFormatter());
    logger.addHandler(fh);
  }

  LoggerLocator.count++;
  LoggerLocator.loggerMap.put(id, logger);
}


我的问题是,当我执行一些将大量请求发送到服务器的扩展测试时,我在每个请求中都打印了count变量,该变量的值为1,但取而代之的是获取2和2个文件的值名称mylog_ {id} .log,mylog_ {id} .log.1

是否有可能在创建第一个Logger并分配给HashMap之前loggerMap为空,而LoggerLocator.loggerMap.containsKey(id)中另一个线程为假?

最佳答案

是的,不仅在创建第一个记录器之前loggerMap是空的,而且绝对肯定是空的。您将变量定义为一个空映射。如果您想一次将对地图的访问限制为一个线程,则很可能需要在某处使用syncrhonized关键字。另外,我不建议将LoggerLocator.count++;LoggerLocator.loggerMap.put(id, logger);放在任何方法之外。这让我很反感。您的方法getLoggerconfigure可能也应该是静态的,而类定义也应该是abstract,以避免能够/必须实例化LoggerLocator的实例。

10-06 05:11