log4j2 LogManager.getLogger()是线程安全的吗?

时间:2018-08-22 11:32:38

标签: java log4j2

当我执行以下代码时,该日志事件仅记录一次。我正在使用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版本2.7
  • IntelliJ Idea 2018.1.5

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>

1 个答案:

答案 0 :(得分:1)

这不是线程安全的。记录器未记录初始消息,因为默认情况下它已配置为ERROR级,然后重新配置为INFO。您可以通过将calculate()中的日志记录方法从info()更改为error()来进行检查-您将收到全部3条消息。

要修复此问题,需要在弄乱线程之前重新配置记录器。 例如,您可以创建一个记录器字段:

private final Logger logger = LogManager.getLogger();

并在这样的计算方法中使用:

public void calculate() {
  loger.info( "total is ..." );
}

此外,每次调用calculate()时,它都会通过getLogger()方法为您节省记录器分辨率。

希望有帮助。