当我执行以下代码时,该日志事件仅记录一次。我正在使用log4j2记录器。但是,当我使用java.util.logger
时,所有3个日志事件均已成功发布。
public class TestLoggingMDC
{
public static void main( String[] args ) throws InterruptedException
{
System.setProperty( "log4j.configurationFile", "log4j2.xml" );//set path here to log4j2 config file
ExecutorService executor = Executors.newFixedThreadPool( 3 );
TestLoggingMDC testLoggingMDC = new TestLoggingMDC();
for ( int i = 0; i < 3; i++ )
{
Runnable runnableTask = testLoggingMDC::calculate;
executor.execute( runnableTask );
}
executor.awaitTermination( 5, TimeUnit.SECONDS );
}
public void calculate()
{
//java.util.logging.Logger.getLogger( "testMDC" ).info( "total is ..." );//this works. log 3 time
LogManager.getLogger( ).info( "total is ..." );//this does not
}
}
当我同步计算方法public synchronized void calculate()
或获得类锁时,如下所示,它可以按预期工作。
public void calculate()
{
synchronized ( LogManager.class )
{
LogManager.getLogger().info( "total is ..." );
}
}
log4j2是线程安全的,但是似乎LogManager.getLogger()
不是线程安全的吗?还是我错过了什么?
请注意,我尝试不使用ExecutorService
(使用java.lang.Thread
)执行线程,结果是相同的。
log4j2配置文件:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="INFO">
<Appenders>
<Console name="ConsoleAppender" target="SYSTEM_OUT">
<PatternLayout pattern="%d{HH:mm:ss,SSS} [%t] %-5p %c{36} - %m%n"/>
</Console>
<File name="fileAppender" fileName="out/MDCTest.log">
<PatternLayout>
<Pattern>%X{id} %m%n</Pattern>
</PatternLayout>
</File>
</Appenders>
<Loggers>
<Root level="INFO">
<AppenderRef ref="ConsoleAppender"/>
</Root>
<Logger name="testMDC" level="ALL">
<AppenderRef ref="fileAppender"/>
</Logger>
</Loggers>
</Configuration>
答案 0 :(得分:1)
这不是线程安全的。记录器未记录初始消息,因为默认情况下它已配置为ERROR
级,然后重新配置为INFO
。您可以通过将calculate()
中的日志记录方法从info()
更改为error()
来进行检查-您将收到全部3条消息。
要修复此问题,需要在弄乱线程之前重新配置记录器。 例如,您可以创建一个记录器字段:
private final Logger logger = LogManager.getLogger();
并在这样的计算方法中使用:
public void calculate() {
loger.info( "total is ..." );
}
此外,每次调用calculate()时,它都会通过getLogger()方法为您节省记录器分辨率。
希望有帮助。