小師妹學JavaIO之:try with和它的底層原理

簡介

小師妹是個java初學者,最近正在學習使用java IO,作爲大師兄的我自然要給她最給力的支持了。一起來看看她都遇到了什麼問題和問題是怎麼被解決的吧。
在這裏插入圖片描述

IO關閉的問題

這一天,小師妹一臉鬱悶的問我:F師兄,我學Java IO也有好多天了,最近寫了一個例子,讀取一個文件沒有問題,但是讀取很多個文件就會告訴我:”Can’t open so many files“,能幫我看看是什麼問題嗎?

更多內容請訪問www.flydean.com

小師妹的要求當然不能拒絕,我立馬響應:可能打開文件太多了吧,教你兩個命令,查看最大文件打開限制。

一個命令是 ulimit -a

第二個命令是

ulimit -n
256

看起來是你的最大文件限制太小了,只有256個,調大一點就可以了。

小師妹卻說:不對呀F師兄,我讀文件都是一個一個讀的,沒有同時開這麼多文件喲。

好吧,看下你寫的代碼吧:

BufferedReader bufferedReader = null;
        try {
            String line;
            bufferedReader = new BufferedReader(new FileReader("trywith/src/main/resources/www.flydean.com"));
            while ((line = bufferedReader.readLine()) != null) {
                log.info(line);
            }
        } catch (IOException e) {
            log.error(e.getMessage(), e);
        }

看完代碼,問題找到了,小師妹,你的IO沒有關閉,應該在使用之後,在finally裏面把你的reader關閉。

下面這段代碼就行了:

BufferedReader bufferedReader = null;
        try {
            String line;
            bufferedReader = new BufferedReader(new FileReader("trywith/src/main/resources/www.flydean.com"));
            while ((line = bufferedReader.readLine()) != null) {
                log.info(line);
            }
        } catch (IOException e) {
            log.error(e.getMessage(), e);
        } finally {
            try {
                if (bufferedReader != null){
                 bufferedReader.close();
                }
            } catch (IOException ex) {
                log.error(ex.getMessage(), ex);
            }
        }

小師妹道了一聲謝,默默的去改代碼了。

使用try with resource

過了半個小時 ,小師妹又來找我了,F師兄,現在每段代碼都要手動添加finally,實在是太麻煩了,很多時候我又怕忘記關閉IO了,導致程序出現無法預料的異常。你也知道我這人從來就怕麻煩,有沒有什麼簡單的辦法,可以解決這個問題呢?

那麼小師妹你用的JDK版本是多少?

小師妹不好意思的說:雖然最新的JDK已經到14了,我還是用的JDK8.

JDK8就夠了,其實從JDK7開始,Java引入了try with resource的新功能,你把使用過後要關閉的resource放到try裏面,JVM會幫你自動close的,是不是很方便,來看下面這段代碼:

try (BufferedReader br = new BufferedReader(new FileReader("trywith/src/main/resources/www.flydean.com")))
        {
            String sCurrentLine;
            while ((sCurrentLine = br.readLine()) != null)
            {
                log.info(sCurrentLine);
            }
        } catch (IOException e) {
            log.error(e.getMessage(), e);
        }

try with resource的原理

太棒了,小師妹非常開心,然後又開始問我了:F師兄,什麼是resource呀?爲什麼放到try裏面就可以不用自己close了?

resource就是資源,可以打開個關閉,我們可以把實現了java.lang.AutoCloseable接口的類都叫做resource。

先看下AutoCloseable的定義:

public interface AutoCloseable {
        void close() throws Exception;
}

AutoCloseable定義了一個close()方法,當我們在try with resource中打開了AutoCloseable的資源,那麼當try block執行結束的時候,JVM會自動調用這個close()方法來關閉資源。

我們看下上面的BufferedReader中close方法是怎麼實現的:

public void close() throws IOException {
    synchronized (lock) {
        if (in == null)
            return;
        in.close();
        in = null;
        cb = null;
    }
}

自定義resource

小師妹恍然大悟:F師兄,那麼我們是不是可以實現AutoCloseable來創建自己的resource呢?

當然可以了,我們舉個例子,比如給你解答完這個問題,我就要去吃飯了,我們定義這樣一個resource類:

public class CustResource implements AutoCloseable {

    public void helpSister(){
        log.info("幫助小師妹解決問題!");
    }

    @Override
    public void close() throws Exception {
        log.info("解決完問題,趕緊去吃飯!");
    }

    public static void main(String[] args) throws Exception {
       try( CustResource custResource= new CustResource()){
           custResource.helpSister();
       }
    }
}

運行輸出結果:

[main] INFO com.flydean.CustResource - 幫助小師妹解決問題!
[main] INFO com.flydean.CustResource - 解決完問題,趕緊去吃飯!

總結

最後,小師妹的問題解決了,我也可以按時吃飯了。

本文的例子https://github.com/ddean2009/learn-java-io-nio

本文作者:flydean程序那些事

本文鏈接:http://www.flydean.com/io-try-with/

本文來源:flydean的博客

歡迎關注我的公衆號:程序那些事,更多精彩等着您!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章