我正在使用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);
放在任何方法之外。这让我很反感。您的方法getLogger
和configure
可能也应该是静态的,而类定义也应该是abstract
,以避免能够/必须实例化LoggerLocator的实例。