使用apache log解决高并发下log4j引起大量线程block问题

由于项目用户量比较大,测试同事采用两百并发进行测试,在测试查过程中,查看jvm 虚拟机发现很多日志线程出现BLOCKED,

结果如下:

"http-saoma%2F192.168.6.162-8097-184" daemon prio=10 tid=0x00002aaab0ecc800 nid=0x2d7a waiting for monitor entry [0x0000000045fa9000]
   java.lang.Thread.State: BLOCKED (on object monitor)
	at org.apache.log4j.Category.callAppenders(Category.java:204)
	- waiting to lock <0x00000007800020a0> (a org.apache.log4j.spi.RootLogger)
	at org.apache.log4j.Category.forcedLog(Category.java:391)
	at org.apache.log4j.Category.log(Category.java:856)
	at org.slf4j.impl.Log4jLoggerAdapter.info(Log4jLoggerAdapter.java:304)

通过日志结果可以看出问题是出在org.apache.log4j.Category.callAppenders方法中,下面是该方法的代码:

/**
     Call the appenders in the hierrachy starting at
     <code>this</code>.  If no appenders could be found, emit a
     warning.

     <p>This method calls all the appenders inherited from the
     hierarchy circumventing any evaluation of whether to log or not
     to log the particular log request.

     @param event the event to log.  
*/
  public void callAppenders(LoggingEvent event) {
    int writes = 0;

    for(Category c = this; c != null; c=c.parent) {
      // Protected against simultaneous call to addAppender, removeAppender,...
      synchronized(c) {
	if(c.aai != null) {
	  writes += c.aai.appendLoopOnAppenders(event);
	}
	if(!c.additive) {
	  break;
	}
      }
    }

    if(writes == 0) {
      repository.emitNoAppenderWarning(this);
    }
  }

我们从上面可以看出在该方法中有个synchronized同步锁,同步锁就会导致线程竞争,那么在大并发情况下将会出现性能问题,同会引

起线程BLOCKED问题。

那怎样解决这个问题呢?

我们可以使用Apache log 解决这个问题,代码如下:

private static final Log log = LogFactory.getLog("xxx");  


通过测试发现,以前org.apache.log4j.Category.callAppenders线程BLOCKED问题没有了。大家以后遇到这个问题可以采取这个方式解决。

你可能感兴趣的:(jvm,log4j,log,BLOCKED,callAppenders)