簡介
小師妹是個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的博客
歡迎關注我的公衆號:程序那些事,更多精彩等着您!