记录器在HashMap中

时间:2014-12-05 21:09:06

标签: java logging

我使用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);
}

我的问题是,当我做一些extress测试向服务器发送大量请求时,我在每个请求中打印了count变量,预计值为1,但不是这样得到值2和2个文件,名称为mylog_ {id} .log,mylog_ {id} .log.1

在创建第一个Logger并分配给HashMap并且另一个线程在LoggerLocator.loggerMap.containsKey(id)中变为false之前,logibMap是否为空?

2 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分:1)

由于您基本上是在进行延迟初始化,因此您需要双重检查习语:

if (!map.containsKey(id)){
    synchronized(map){
        if (!map.containsKey(id)){
           initialize()
        }
    }
}

第一次检查后锁定可确保在不执行锁定时快速进行常规访问。执行第二次检查可确保在您等待锁定时没有其他人初始化锁定。这样就可以完成一次初始化。