我们有很多类代码,其中包含一些样板,如下所示:
private static Logger logger = null;
private static Logger getLogger() {
if (logger == null) {
logger = Logger.getLogger(MyClass.class);
}
return logger;
}
这个想法是该类可以将调试内容记录到Logger中。需要记录某些内容的第一个代码调用getLogger()并使记录器存在。
关于这种模式,我有几件我不喜欢的事情。首先,单例getLogger()未同步并同步,而正确将无故给以后的每次调用带来负担。
我真的很想能够将其压缩为:
private static final Logger logger = Logger.getLogger(MyClass.class);
然后,我可以直接引用记录器,而不必担心单例 getter 。
我担心的问题是,即使没有调用记录器,这样做也会导致在加载类时创建一个记录器。我有10,000+个奇数类,都调用getLogger(),所以我实际上在这里创建了Logger的多少实例?如果我的log4j属性包含一些追加程序,是我只是一遍又一遍地引用同一记录器,还是我要创建10,000个这样的东西?
最佳答案
如果您使用默认的Log4j配置(即默认的LoggerRepository,DefaultCategoryFactory等),则将创建10'000个Logger实例。它们消耗多少内存?除上帝和您的探查者以外,没有人知道这一点。 (我猜只有后者会告诉你)。
如果对于您的环境而言,内存占用过多,则将Logger初始化移至静态内部类,如下所示:
static class LoggerHolder {
static Logger logger = Logger.getLogger(MyClass.class);
}
private static Logger getLogger() {
return LoggerHolder.logger;
}
这样,
Logger
的实例将仅在第一个getLogger
调用中创建。 (此技术称为按需初始化持有人(IODH),它是线程安全的,并且同步开销为零)。我可以给你一个建议吗?考虑用SLF4J + Logback库的组合替换Log4J。它们由完全相同的作者撰写,并被描述为“
a successor to the popular log4j project, picking up where log4j leaves off
”。您可以在this SO thread中阅读更多内容。关于java - 从静态最终变量初始值设定项获取Logger效率高吗?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/7318934/