由于项目用户量比较大,测试同事采用两百并发进行测试,在测试查过程中,查看jvm 虚拟机发现很多日志线程出现BLOCKED,
结果如下:
起线程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同步锁,同步锁就会导致线程竞争,那么在大并发情况下将会出现性能问题,同会引
那怎样解决这个问题呢?
我们可以使用Apache log 解决这个问题,代码如下:
private static final Log log = LogFactory.getLog("xxx");
通过测试发现,以前org.apache.log4j.Category.callAppenders线程BLOCKED问题没有了。大家以后遇到这个问题可以采取这个方式解决。