Log4j异步appender用法?

时间:2013-10-18 07:11:42

标签: java multithreading logging log4j java-ee-6

我正在使用log4j AsyncAppender。我编写了自己的appender来自定义记录器,如下所示。

公共类MyAppender扩展了AppenderSkeleton {

@Override
public void close() {

}


@Override
public boolean requiresLayout() {
    return false;
}


@Override
protected void append(LoggingEvent event) {

//Here am doing some logic which will connect database and fetch some records.  

}

}

我的log4j配置:

<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" debug="false">

    <!-- Appenders -->

    <appender name="stdout" class="com.sample.MyAppender">
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="%d %p [%c] - %m%n"/>
        </layout>
    </appender>


    <appender name="ASYNC" class="org.apache.log4j.AsyncAppender">
        <param name="BufferSize" value="500"/>
        <appender-ref ref="stdout"/>
    </appender>


    <root>
        <level value="INFO" />
        <appender-ref ref="ASYNC" />
    </root>

</log4j:configuration>

现在一切正常。我MyAppender我将触发Select查询并从表中获取一些详细信息,并使用java mail API发送这些详细信息。当我使用AsyncAppender时,它不会阻止现有的运行线程并且MyAppender逻辑是异步执行的。我的问题是主线程是否在MyAppender逻辑完成之前完成其执行然后是否有任何保证即使主线程完成执行,MyAppender中的逻辑也会完成?

谢谢!

2 个答案:

答案 0 :(得分:1)

已经过了一年,但我会在我之后回答别人的利益。安全关闭所有appender并确保在日志记录完成之前JVM没有关闭的正确方法是调用LogManager.shutdown();。我还没有确认,但在Log4j 2中显然没有必要,因为它会自动向JVM注册一个关闭钩子。

答案 1 :(得分:0)

快速查看AsyncAppendersource code。似乎异步处理日志记录事件的线程被设置为守护程序线程。因此,当主线程退出日志记录线程时也会退出,可能是队列中未处理的日志记录请求。

setDaemon(true)调用上方还有一条评论:用户有责任在退出前关闭appender。(意味着关闭记录器线程后将完成其排队的记录事件,请参阅close()方法代码段

  public  AsyncAppender() {
    appenders = new AppenderAttachableImpl();
    aai = appenders;
    dispatcher =  new Thread(new Dispatcher(this, buffer, discardMap, appenders));

    // It is the user's responsibility to close appenders before
    // exiting.
    dispatcher.setDaemon(true);


    // set the dispatcher priority to lowest possible value
    //        dispatcher.setPriority(Thread.MIN_PRIORITY);
    dispatcher.setName("AsyncAppender-Dispatcher-" + dispatcher.getName());
    dispatcher.start();
  }



    //Close this AsyncAppender by interrupting the dispatcher 
    //thread which will process all pending events before exiting.
  public void  close() {
    ...

     try {
      dispatcher.join();
    } catch (InterruptedException e) {
      Thread.currentThread().interrupt();
      org.apache.log4j.helpers.LogLog.error(
        "Got an InterruptedException while waiting for the "
                        + "dispatcher to finish.", e);
    }
    ...
  }