大的逻辑:
当Logging Event进入AsyncAppender后,将event填入buffer中,
AsyncAppender有个线程类Worker,它是一个简单的线程类,是AsyncAppender的后台线程,所要做的工作是:从buffer中取出event交给对应的appender-ref 进行后面的日志推送。
public void append(final LoggingEvent event) {
//
// if dispatcher thread has died then
// append subsequent events synchronously
// 如果dispatcher线程不在了,直接调用各个appender的同步写方法,确保日志的写入
if ((dispatcher == null) || !dispatcher.isAlive() || (bufferSize <= 0)) {
synchronized (appenders) {
appenders.appendLoopOnAppenders(event);
}
return;
}
// Set the NDC and thread name for the calling thread as these
// LoggingEvent fields were not set at event creation time.
event.getNDC();
event.getThreadName();
// Get a copy of this thread's MDC.
event.getMDCCopy();
if (locationInfo) {
event.getLocationInformation();
}
synchronized (buffer) { //这里将buffer资源对象当锁,可以想象到所有操作buffer的方法都必须做同步。
while (true) {
int previousSize = buffer.size(); //当前buffer的大小
if (previousSize < bufferSize) {
buffer.add(event);
//
// if buffer had been empty
// signal all threads waiting on buffer
// to check their conditions.
// buffer空了,则唤醒所有线程
if (previousSize == 0) {
buffer.notifyAll(); //notifyAll()方法是Object对象的方法,而不是Thread对象的方法。
}
break;
}
//
// Following code is only reachable if buffer is full
// 如果buffer写满了,才会走到下面的代码流程
//
// if blocking and thread is not already interrupted
// and not the dispatcher then
// wait for a buffer notification
boolean discard = true;
if (blocking //buffer满就阻塞的标志位
&& !Thread.interrupted()
&& Thread.currentThread() != dispatcher) {
try {
buffer.wait(); //满了就等待把
discard = false;
} catch (InterruptedException e) {
//
// reset interrupt status so
// calling code can see interrupt on
// their next wait or sleep.
Thread.currentThread().interrupt(); //这里处理interrupt的方法值得体会:)当然可以学会套用这个模板
}
}
//
// if blocking is false or thread has been interrupted
// add event to discard map.
//
if (discard) { //如果没能成功进入wait(),放到丢弃消息map中保存
String loggerName = event.getLoggerName();
DiscardSummary summary = (DiscardSummary) discardMap.get(loggerName);
if (summary == null) {
summary = new DiscardSummary(event);
discardMap.put(loggerName, summary);
} else {
summary.add(event);
}
break;
}
}
}
}