Log4j AsyncAppender 源码

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

总结:

  1. 一个缓冲区buffer,为了减少读写硬盘次数,提高cpu效率,避免过多的中断切换。
  2. 一个Map对生产者速度远大于消费者地补救措施
  3. 一个后台线程不断进行写入磁盘地操作
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值