java log4j 工作原理,log4j运行原理分析

public void append(final LoggingEvent event) {

//

// if dispatcher thread has died then

// append subsequent events synchronously

// See bug 23021

//如果消费线程为空,或者不是存活的,或者队列长度小于等于0,这里直接变为同步执行了

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();

}

event.getRenderedMessage();

event.getThrowableStrRep();

//锁住队列,保证线程安全

synchronized (buffer) {

while (true) {

int previousSize = buffer.size();

//队列有可用空间则直接放日志进去

if (previousSize < bufferSize) {

buffer.add(event);

//

// if buffer had been empty

// signal all threads waiting on buffer

// to check their conditions.

//

//如果是队列内容为空,有可能消费完,有可能是首次进队列,那么此时的nofityAll是为了唤醒同时监听buffer对象的消费者

if (previousSize == 0) {

buffer.notifyAll();

}

break;

}

//

// Following code is only reachable if buffer is full

//

//

// if blocking and thread is not already interrupted

// and not the dispatcher then

// wait for a buffer notification

boolean discard = true;

//如果队列满了以后,看它的阻塞策略是否为true,如果是,检查当前线程是否已经被中断,保证当前的线程不是消费线程,此时只能进入线程等待了,因为策略不允许丢弃

//等的过程wait是释放对buffer的持有,锁释放的两种清空如下,所以这是否消费者可以努力的去消费把,队列给腾出空间来,消费者消费过程中也会notifyAll,唤醒等待中的生产者线程

//1.该线程的同步方法、同步代码块执行完、该线程同步方法、同步代码块中遇到return,break、该线程同步方法、同步代码块中发生了未处理的Exception、Error

//2.其他线程执行了同步监听器对象的wait()、其他线程执行了当前线程的stop

if (blocking

&& !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();

}

}

//

// if blocking is false or thread has been interrupted

// add event to discard map.

//如果线程没有进入等待,那怎么办,队列还是满的,好办直接丢吧,丢了哪些需要记下来哦

if (discard) {

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;

}

}

}

}

消费者: public void run() {

boolean isActive = true;

//

// if interrupted (unlikely), end thread

//

try {

//

// loop until the AsyncAppender is closed.

//

while (isActive) {

LoggingEvent[] events = null;

//

// extract pending events while synchronized

// on buffer

//锁住该对象保证多线程同步

synchronized (buffer) {

int bufferSize = buffer.size();

isActive = !parent.closed;

while ((bufferSize == 0) && isActive) {

buffer.wait();

//空队列,就等待吧,节省CPU资源,因为这里等待了,所以生产者哪里对空队列加入消息后会notify它,是需要唤醒消费线程

bufferSize = buffer.size();

isActive = !parent.closed;

}

if (bufferSize > 0) {

events = new LoggingEvent[bufferSize + discardMap.size()];

buffer.toArray(events);

//

// add events due to buffer overflow

//

int index = bufferSize;

for (

Iterator iter = discardMap.values().iterator();

iter.hasNext();) {

events[index++] = ((DiscardSummary) iter.next()).createEvent();

}

//

// clear buffer and discard map

//

buffer.clear();

discardMap.clear();

//

// allow blocked appends to continue

buffer.notifyAll();

//队列内容已经被移动到了events里,队列有了足够的空间,可以把因为队列满而进行等待的线程唤醒了,因为消息不能丢啊

//正好消费者的线程也把锁释放了,生产者线程被唤醒后,下一个while true循环就可以继续往队列里放东西了

}

}

//

// process events after lock on buffer is released.

//

if (events != null) {

for (int i = 0; i < events.length; i++) {

synchronized (appenders) {

appenders.appendLoopOnAppenders(events[i]);

}

}

}

}

} catch (InterruptedException ex) {

Thread.currentThread().interrupt();

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值