欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

logback?OutputStreamAppender高效日志輸出源碼解析

 更新時(shí)間:2023年10月29日 17:05:21   作者:codecraft  
這篇文章主要介紹了為大家logback?OutputStreamAppender日志輸出效率提升示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

本文主要研究一下logback的OutputStreamAppender

OutputStreamAppender

logback-core/src/main/java/ch/qos/logback/core/OutputStreamAppender.java

public class OutputStreamAppender<E> extends UnsynchronizedAppenderBase<E> {
    /**
     * It is the encoder which is ultimately responsible for writing the event to an
     * {@link OutputStream}.
     */
    protected Encoder<E> encoder;
    /**
     * All synchronization in this class is done via the lock object.
     */
    protected final ReentrantLock streamWriteLock = new ReentrantLock(false);
    /**
     * This is the {@link OutputStream outputStream} where output will be written.
     */
    private OutputStream outputStream;
    boolean immediateFlush = true;
    //......
}
OutputStreamAppender繼承了UnsynchronizedAppenderBase,它定義了encoder、streamWriteLock、outputStream、immediateFlush屬性

start

/**
     * Checks that requires parameters are set and if everything is in order,
     * activates this appender.
     */
    public void start() {
        int errors = 0;
        if (this.encoder == null) {
            addStatus(new ErrorStatus("No encoder set for the appender named \"" + name + "\".", this));
            errors++;
        }
        if (this.outputStream == null) {
            addStatus(new ErrorStatus("No output stream set for the appender named \"" + name + "\".", this));
            errors++;
        }
        // only error free appenders should be activated
        if (errors == 0) {
            super.start();
        }
    }
其start方法主要是校驗(yàn)encoder、outputStream,然后執(zhí)行super.start()

stop

/**
     * Stop this appender instance. The underlying stream or writer is also closed.
     * 
     * <p>
     * Stopped appenders cannot be reused.
     */
    public void stop() {
        if(!isStarted())
            return;
        streamWriteLock.lock();
        try {
            closeOutputStream();
            super.stop();
        } finally {
            streamWriteLock.unlock();
        }
    }
    protected void closeOutputStream() {
        if (this.outputStream != null) {
            try {
                // before closing we have to output out layout's footer
                encoderClose();
                this.outputStream.close();
                this.outputStream = null;
            } catch (IOException e) {
                addStatus(new ErrorStatus("Could not close output stream for OutputStreamAppender.", this, e));
            }
        }
    }
    void encoderClose() {
        if (encoder != null && this.outputStream != null) {
            try {
                byte[] footer = encoder.footerBytes();
                writeBytes(footer);
            } catch (IOException ioe) {
                this.started = false;
                addStatus(new ErrorStatus("Failed to write footer for appender named [" + name + "].", this, ioe));
            }
        }
    }
其stop方法主要是加鎖然后closeOutputStream,再執(zhí)行super.stop;closeOutputStream主要是先寫(xiě)入encoder.footerBytes(),再關(guān)閉outputStream

append

protected void append(E eventObject) {
        if (!isStarted()) {
            return;
        }
        subAppend(eventObject);
    }
    protected void subAppend(E event) {
        if (!isStarted()) {
            return;
        }
        try {
            // this step avoids LBCLASSIC-139
            if (event instanceof DeferredProcessingAware) {
                ((DeferredProcessingAware) event).prepareForDeferredProcessing();
            }
            writeOut(event);
        } catch (IOException ioe) {
            // as soon as an exception occurs, move to non-started state
            // and add a single ErrorStatus to the SM.
            this.started = false;
            addStatus(new ErrorStatus("IO failure in appender", this, ioe));
        }
    }    
    protected void writeOut(E event) throws IOException {
        byte[] byteArray = this.encoder.encode(event);
        writeBytes(byteArray);
    }
    private void writeBytes(byte[] byteArray) throws IOException {
        if (byteArray == null || byteArray.length == 0)
            return;
        streamWriteLock.lock();
        try {
            writeByteArrayToOutputStreamWithPossibleFlush(byteArray);
        } finally {
            streamWriteLock.unlock();
        }
    }
    /**
     * A simple method to write to an outputStream and flush the stream if immediateFlush is set to true.
     *
     * @since 1.3.9/1.4.9
     */
    protected final void writeByteArrayToOutputStreamWithPossibleFlush(byte[] byteArray) throws IOException {
        this.outputStream.write(byteArray);
        if (immediateFlush) {
            this.outputStream.flush();
        }
    }
append方法主要是執(zhí)行writeOut操作,如果是DeferredProcessingAware類型,會(huì)先執(zhí)行prepareForDeferredProcessing;writeOut先執(zhí)行encoder的encode,然后加鎖執(zhí)行outputStream.write(byteArray),如果需要immediateFlush則會(huì)執(zhí)行outputStream.flush()

setOutputStream

public void setOutputStream(OutputStream outputStream) {
        streamWriteLock.lock();
        try {
            // close any previously opened output stream
            closeOutputStream();
            this.outputStream = outputStream;
            if (encoder == null) {
                addWarn("Encoder has not been set. Cannot invoke its init method.");
                return;
            }
            encoderInit();
        } finally {
            streamWriteLock.unlock();
        }
    }
    protected void closeOutputStream() {
        if (this.outputStream != null) {
            try {
                // before closing we have to output out layout's footer
                encoderClose();
                this.outputStream.close();
                this.outputStream = null;
            } catch (IOException e) {
                addStatus(new ErrorStatus("Could not close output stream for OutputStreamAppender.", this, e));
            }
        }
    }    
    void encoderInit() {
        if (encoder != null && this.outputStream != null) {
            try {
                byte[] header = encoder.headerBytes();
                writeBytes(header);
            } catch (IOException ioe) {
                this.started = false;
                addStatus(
                        new ErrorStatus("Failed to initialize encoder for appender named [" + name + "].", this, ioe));
            }
        }
    }
setOutputStream方法會(huì)加鎖執(zhí)行closeOutputStream、給outputStream賦值,再執(zhí)行encoderInit;closeOutputStream主要是為了清空前面遺留的數(shù)據(jù),encoderInit則先寫(xiě)入encoder.headerBytes()

小結(jié)

logback的OutputStreamAppender主要是通過(guò)非公平的ReentrantLock來(lái)寫(xiě)入outputStream。

以上就是logback OutputStreamAppender日志輸出效率提升源碼解析的詳細(xì)內(nèi)容,更多關(guān)于logback OutputStreamAppender的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Spring Boot 集成Shiro的多realm實(shí)現(xiàn)以及shiro基本入門(mén)教程

    Spring Boot 集成Shiro的多realm實(shí)現(xiàn)以及shiro基本入門(mén)教程

    這篇文章主要介紹了Spring Boot 集成Shiro的多realm實(shí)現(xiàn)以及shiro基本入門(mén),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-10-10
  • java設(shè)計(jì)模式-裝飾者模式詳解

    java設(shè)計(jì)模式-裝飾者模式詳解

    這篇文章主要介紹了Java設(shè)計(jì)模式之裝飾者模式詳解和代碼實(shí)例,Decorator模式(別名Wrapper):動(dòng)態(tài)將職責(zé)附加到對(duì)象上,若要擴(kuò)展功能,裝飾者提供了比繼承更具彈性的代替方案,需要的朋友可以參考下
    2021-07-07
  • Springboot apollo原理及使用方法詳解

    Springboot apollo原理及使用方法詳解

    這篇文章主要介紹了Springboot apollo原理及使用方法詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-06-06
  • 深入了解java 8的函數(shù)式編程

    深入了解java 8的函數(shù)式編程

    函數(shù)式編程并不是Java新提出的概念,其與指令編程相比,強(qiáng)調(diào)函數(shù)的計(jì)算比指令的計(jì)算更重要;與過(guò)程化編程相比,其中函數(shù)的計(jì)算可以隨時(shí)調(diào)用。下面我們來(lái)詳細(xì)了解一下吧
    2019-06-06
  • 關(guān)于Android觸摸事件分發(fā)的原理詳析

    關(guān)于Android觸摸事件分發(fā)的原理詳析

    觸摸事件分發(fā)機(jī)制一直以來(lái)都是Android中比較重要的一大塊,自定義view,各種復(fù)雜的自定義手勢(shì)交互都與觸摸事件分發(fā)機(jī)制關(guān)系密,下面這篇文章主要給大家介紹了關(guān)于Android觸摸事件分發(fā)原理的相關(guān)資料,需要的朋友可以參考下
    2022-01-01
  • Java深入分析與解決Top-K問(wèn)題

    Java深入分析與解決Top-K問(wèn)題

    TopK問(wèn)題即在N個(gè)數(shù)中找出最大的前K個(gè),這篇文章將詳細(xì)講解三種方法解決TopK問(wèn)題,文中代碼具有一定參考價(jià)值,快跟隨小編一起學(xué)習(xí)一下吧
    2022-04-04
  • Mybatis攔截器如何實(shí)現(xiàn)數(shù)據(jù)權(quán)限過(guò)濾

    Mybatis攔截器如何實(shí)現(xiàn)數(shù)據(jù)權(quán)限過(guò)濾

    本文介紹了MyBatis攔截器的使用,通過(guò)實(shí)現(xiàn)Interceptor接口對(duì)SQL進(jìn)行處理,實(shí)現(xiàn)數(shù)據(jù)權(quán)限過(guò)濾功能,通過(guò)在本地線程變量中存儲(chǔ)數(shù)據(jù)權(quán)限相關(guān)信息,并在攔截器的intercept方法中進(jìn)行SQL增強(qiáng)處理
    2024-12-12
  • Java基礎(chǔ)之簡(jiǎn)單的圖片處理

    Java基礎(chǔ)之簡(jiǎn)單的圖片處理

    這篇文章主要介紹了Java基礎(chǔ)之簡(jiǎn)單的圖片處理,文中有非常詳細(xì)的代碼示例,對(duì)正在學(xué)習(xí)java的小伙伴們有非常好的幫助,需要的朋友可以參考下
    2021-04-04
  • Java_int、double型數(shù)組常用操作工具類(分享)

    Java_int、double型數(shù)組常用操作工具類(分享)

    下面小編就為大家?guī)?lái)一篇Java_int、double型數(shù)組常用操作工具類(分享)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-08-08
  • 關(guān)于maven使用過(guò)程中無(wú)法導(dǎo)入依賴的一些總結(jié)

    關(guān)于maven使用過(guò)程中無(wú)法導(dǎo)入依賴的一些總結(jié)

    這篇文章主要介紹了關(guān)于maven使用過(guò)程中無(wú)法導(dǎo)入依賴的一些總結(jié),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-08-08

最新評(píng)論