记录器上阻塞的Java线程

时间:2013-02-07 08:33:30

标签: java multithreading logging jboss log4j

我们的Java(Web)应用程序在JBoss 6x中运行。 当报告缓慢时:

  1. 线程堆栈转储(详情如下)
  2. 检查内存 - 发现内存使用率非常高,几乎触及Max Allowed Heap Size,但没有Out of Memory。
  3. 线程堆栈转储显示在使用以下类型的错误记录时阻止的大多数线程:

    waiting for monitor entry [0x000000004b6be000]
       java.lang.Thread.State: BLOCKED (on object monitor)
        at org.jboss.logmanager.handlers.WriterHandler.doPublish(WriterHandler.java:59)
        - waiting to lock <0x00002aaac9a2de68> (a java.lang.Object)
        at org.jboss.logmanager.ExtHandler.publish(ExtHandler.java:64)
    

    就像这样:

       java.lang.Thread.State: BLOCKED (on object monitor)
        at java.io.PrintStream.println(PrintStream.java:756)
    - waiting to lock <0x00002aaac9817a08> (a com.whatever.SomeClass)
    at com.something.ThatClass.thatMethod(ThatClass.java:169)
    

    com.whatever.SomeClass使用org.apache.log4j.Logger
    我们使用Log4j进行日志记录。

    似乎线程在某些日志记录操作中都被阻止。 过去也出现过此问题,并且似乎是随机的,它会减慢/停止应用程序。

    有什么想法吗?

1 个答案:

答案 0 :(得分:2)

Jasper,所有日志框架都有一个synchronized块,用于将数据写入磁盘。这是为了防止在多于1个线程写入日志时乱写日志(您发布了一个示例 - java.io.PrintStream.println上的BLOCKED线程)。

但是有一个解决方案,即使用asynchronous appender。在工作中,我们有一些高吞吐量/低延迟应用程序,我们必须配置它以防止线程争用。

当您使用异步appender时需要考虑的一件事是,如果您的应用程序崩溃或被强制终止,您将看不到日志中的最后一个日志记录语句,因为它们可能不是写入磁盘。