使用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
     this.  If no appenders could be found, emit a
     warning.

     

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问题没有了。大家以后遇到这个问题可以采取这个方式解决。

你可能感兴趣的:(问题集锦,JAVA,java常见问题)