您的位置:首页 > 移动开发

Log4j AsyncAppender 源码

2016-08-10 21:26 357 查看
public class AsyncAppender extends AppenderSkeleton implements AppenderAttachable {
// 默认缓冲区大小
public static final int DEFAULT_BUFFER_SIZE = 128;
// 缓冲区(LoggerEvent)
private final List buffer = new ArrayList();
private final Map discardMap = new HashMap();
// 缓冲区大小
private int bufferSize = 128;
// Error->warn->info->debug appender
AppenderAttachableImpl aai;
private final AppenderAttachableImpl appenders = new AppenderAttachableImpl();
// 后台线程负责写入日志文件
private final Thread dispatcher;

private boolean locationInfo = false;
private boolean blocking = true;

// 构造函数
public AsyncAppender() {
this.aai = this.appenders;
this.dispatcher = new Thread(new AsyncAppender.Dispatcher(this, this.buffer, this.discardMap, this.appenders));
this.dispatcher.setDaemon(true);
this.dispatcher.setName("AsyncAppender-Dispatcher-" + this.dispatcher.getName());
// 启动后台线程
this.dispatcher.start();
}

// 添加输出位置
public void addAppender(Appender newAppender) {
AppenderAttachableImpl var2 = this.appenders;
synchronized(this.appenders) {
this.appenders.addAppender(newAppender);
}
}

public void append(LoggingEvent event) {
if(this.dispatcher != null && this.dispatcher.isAlive() && this.bufferSize > 0) {
// 后台线程存活
event.getNDC();
event.getThreadName();
event.getMDCCopy();
if(this.locationInfo) {
event.getLocationInformation();
}

event.getRenderedMessage();
event.getThrowableStrRep();

// 得到当前Appender的缓冲区
List var11 = this.buffer;
synchronized(this.buffer) {
while(true) {
int previousSize = this.buffer.size();
if(previousSize < this.bufferSize) {
// 当前缓冲区里元素地数目小于最大的缓冲区大小,直接add
this.buffer.add(event);
if(previousSize == 0) {
this.buffer.notifyAll();
}
break;
}

boolean discard = true;
if(this.blocking && !Thread.interrupted() && Thread.currentThread() != this.dispatcher) {
try {
// 停止所有生产者和消费者
this.buffer.wait();
discard = false;
} catch (InterruptedException var8) {
Thread.currentThread().interrupt();
}
}

if(discard) {
String loggerName = event.getLoggerName();
AsyncAppender.DiscardSummary summary = (AsyncAppender.DiscardSummary)this.discardMap.get(loggerName);
if(summary == null) {
summary = new AsyncAppender.DiscardSummary(event);
// 放入缓冲里
this.discardMap.put(loggerName, summary);
} else {
//加入event
summary.add(event);
}
break;
}
}

}
} else {
AppenderAttachableImpl var2 = this.appenders;
synchronized(this.appenders) {
this.appenders.appendLoopOnAppenders(event);
}
}
}
...

private static class Dispatcher implements Runnable {
private final AsyncAppender parent;
private final List buffer;
private final Map discardMap;
private final AppenderAttachableImpl appenders;

public Dispatcher(AsyncAppender parent, List buffer, Map discardMap, AppenderAttachableImpl appenders) {
this.parent = parent;
this.buffer = buffer;
this.appenders = appenders;
this.discardMap = discardMap;
}

public void run() {
boolean isActive = true;

try {
while(isActive) {
LoggingEvent[] ex = null;
List i = this.buffer;
synchronized(this.buffer) {
int bufferSize = this.buffer.size();

for(isActive = !this.parent.closed; bufferSize == 0 && isActive; isActive = !this.parent.closed) {
// 停止所有生产者和消费者
this.buffer.wait();
bufferSize = this.buffer.size();
}

if(bufferSize > 0) {
ex = new LoggingEvent[bufferSize + this.discardMap.size()];
// 获得数组
this.buffer.toArray(ex);
int index = bufferSize;

for(Iterator iter = this.discardMap.values().iterator(); iter.hasNext(); ex[index++] = ((AsyncAppender.DiscardSummary)iter.next()).createEvent()) {
;
// 将DiscardMap的数据重新保存在array里一同持久化
}

// 清空
this.buffer.clear();
this.discardMap.clear();
// 生产者消费者重新被唤醒
this.buffer.notifyAll();
}
}

if(ex != null) {
for(int var12 = 0; var12 < ex.length; ++var12) {
AppenderAttachableImpl var13 = this.appenders;
synchronized(this.appenders) {
// 写入磁盘
this.appenders.appendLoopOnAppenders(ex[var12]);
}
}
}
}
} catch (InterruptedException var11) {
Thread.currentThread().interrupt();
}

}
}

// 解决生产者生产速度远大于消费者消费的速度
private static final class DiscardSummary {
private LoggingEvent maxEvent;
// 丢失了几个
private int count;

public DiscardSummary(LoggingEvent event) {
this.maxEvent = event;
this.count = 1;
}

public void add(LoggingEvent event) {
if(event.getLevel().toInt() > this.maxEvent.getLevel().toInt()) {
// 判断等级
this.maxEvent = event;
}

++this.count;
}

public LoggingEvent createEvent() {
String msg = MessageFormat.format("Discarded {0} messages due to full event buffer including: {1}", new Object[]{new Integer(this.count), this.maxEvent.getMessage()});
return new LoggingEvent("org.apache.log4j.AsyncAppender.DONT_REPORT_LOCATION", Logger.getLogger(this.maxEvent.getLoggerName()), this.maxEvent.getLevel(), msg, (Throwable)null);
}
}
}


总结:

一个缓冲区buffer,为了减少读写硬盘次数,提高cpu效率,避免过多的中断切换。

一个Map对生产者速度远大于消费者地补救措施

一个后台线程不断进行写入磁盘地操作
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: