最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

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

本文主要研究一下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方法主要是校驗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主要是先寫入encoder.footerBytes(),再關閉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類型,會先執(zhí)行prepareForDeferredProcessing;writeOut先執(zhí)行encoder的encode,然后加鎖執(zhí)行outputStream.write(byteArray),如果需要immediateFlush則會執(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方法會加鎖執(zhí)行closeOutputStream、給outputStream賦值,再執(zhí)行encoderInit;closeOutputStream主要是為了清空前面遺留的數(shù)據(jù),encoderInit則先寫入encoder.headerBytes()

小結

logback的OutputStreamAppender主要是通過非公平的ReentrantLock來寫入outputStream。

以上就是logback OutputStreamAppender日志輸出效率提升源碼解析的詳細內容,更多關于logback OutputStreamAppender的資料請關注腳本之家其它相關文章!

相關文章

  • java使用POI實現(xiàn)html和word相互轉換

    java使用POI實現(xiàn)html和word相互轉換

    這篇文章主要為大家詳細介紹了java使用POI實現(xiàn)html和word的相互轉換,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-12-12
  • 如何利用postman完成JSON串的發(fā)送功能(springboot)

    如何利用postman完成JSON串的發(fā)送功能(springboot)

    這篇文章主要介紹了如何利用postman完成JSON串的發(fā)送功能(springboot),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-07-07
  • Java 使用JdbcTemplate 中的queryForList發(fā)生錯誤解決辦法

    Java 使用JdbcTemplate 中的queryForList發(fā)生錯誤解決辦法

    這篇文章主要介紹了Java 使用JdbcTemplate 中的queryForList發(fā)生錯誤解決辦法的相關資料,需要的朋友可以參考下
    2017-07-07
  • Java中Calendar時間操作常用方法詳解

    Java中Calendar時間操作常用方法詳解

    這篇文章主要為大家詳細介紹了Java中Calendar時間操作常用方法,calendar中set方法和靜態(tài)屬性帶來的一些坑,感興趣的小伙伴們可以參考一下
    2016-05-05
  • springmvc4+hibernate4分頁查詢功能實現(xiàn)

    springmvc4+hibernate4分頁查詢功能實現(xiàn)

    本篇文章主要介紹了springmvc4+hibernate4分頁查詢功能實現(xiàn),Springmvc+hibernate成為現(xiàn)在很多人用的框架整合,有興趣的可以了解一下。
    2017-01-01
  • Spring?AOP手寫動態(tài)代理代碼實例

    Spring?AOP手寫動態(tài)代理代碼實例

    這篇文章主要介紹了Spring?AOP手寫動態(tài)代理代碼實例,AOP我們知道,是在不修改源代碼的情況下,為代碼添加一些新功能的技術,通過動態(tài)代理,可以在不修改原始類代碼的前提下,對方法進行攔截和增強,需要的朋友可以參考下
    2024-01-01
  • Java?Stream對象并行處理方法parallel()代碼示例

    Java?Stream對象并行處理方法parallel()代碼示例

    在Java中Stream是一種用于處理集合數(shù)據(jù)的流式操作API,它提供了一種簡潔、靈活、高效的方式來對集合進行各種操作,下面這篇文章主要給大家介紹了關于Java?Stream對象并行處理方法parallel()的相關資料,需要的朋友可以參考下
    2023-11-11
  • SpringBoot中的ImportSelector類動態(tài)加載bean詳解

    SpringBoot中的ImportSelector類動態(tài)加載bean詳解

    這篇文章主要介紹了SpringBoot中的ImportSelector類動態(tài)加載bean詳解,ImportSelector接口是spring中導入外部配置的核心接口,根據(jù)給定的條件(通常是一個或多個注釋屬性)判定要導入那個配置類,在spring自動化配置和@EnableXXX中都有它的存在,需要的朋友可以參考下
    2024-01-01
  • SpringMVC ajax請求的處理方法介紹

    SpringMVC ajax請求的處理方法介紹

    Ajax即異步的 JavaScript和XML,是一種無需重新加載整個網(wǎng)頁的情況下,能夠更新部分模塊的網(wǎng)頁技術,下面這篇文章主要給大家介紹了關于SpringMVC Ajax請求的處理,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下
    2022-11-11
  • Java中的Hashtable源碼詳細解析

    Java中的Hashtable源碼詳細解析

    這篇文章主要介紹了Java中的Hashtable源碼詳細解析,Hashtable 的函數(shù)都是同步的,這意味著它是線程安全的,它的key、value都不可以為null,此外,Hashtable中的映射不是有序的,需要的朋友可以參考下
    2023-11-11

最新評論

拉萨市| 蒙城县| 双辽市| 屏南县| 酒泉市| 北安市| 土默特左旗| 宜昌市| 革吉县| 青海省| 寿阳县| 孟州市| 和龙市| 福州市| 望都县| 山阴县| 芮城县| 阳城县| 平陆县| 广安市| 瑞安市| 曲沃县| 太湖县| 邮箱| 宽城| 济源市| 高雄市| 清远市| 大安市| 芦山县| 恩施市| 宜春市| 望城县| 丽水市| 南江县| 兴和县| 黎川县| 正蓝旗| 新化县| 吴桥县| 连山|