目錄:
-
1、阻塞IO(Block IO)與非阻塞IO(Non-Block IO)
-
1.1、阻塞IO(Block IO)與非阻塞IO(Non-Block IO)區(qū)別
-
1.2、阻塞IO(Block IO)與非阻塞IO(Non-Block IO)類比
-
-
2、同步IO(Syn IO)與異步IO(Asyn IO)
-
2.1、同步IO(Syn IO)和異步IO(Asyn IO)的對比
-
2.2、同步IO和異步IO還是比較抽象,繼續(xù)類比
-
2.2、同步IO和異步IO 類比貨車拉貨
-
-
3、BIO、NIO、AIO
-
3.1、BIO、NIO之間的對比
-
3.2、對比之面向流與面向緩沖區(qū)
-
3.3、對比之阻塞與非阻塞
-
3.4、selector選擇器問世
-
3.5、NIO 和 BIO 讀取磁盤數(shù)據(jù)的對比
-
3.6、BIO、NIO、AIO應用場景
-
-
4、面試常見問題
-
4.1、流按照傳輸?shù)姆较蛟趺捶诸悾?/h6>
-
4.2、流按照傳輸?shù)膯挝辉趺捶诸悾糠殖赡膬煞N流,并且他們的父類叫什么?說一下常用的IO流?
-
4.3、流按實現(xiàn)功能怎么分?
-
4.4、FileInputStream和FileOutputStream 與 BufferedInputStream 和 BufferedOutputStream區(qū)別?
-
4.5、flush() 方法的作用?
-
1、阻塞IO(Block)與非阻塞IO(Non-Block)
1.1、阻塞IO(Block)與非阻塞IO(Non-Block)區(qū)別:
阻塞和非阻塞是服務端進程(線程)
在訪問數(shù)據(jù)的時候,數(shù)據(jù)是否準備就緒的一種處理方式:
- 阻塞(Block):需要等待
緩沖區(qū)
中的數(shù)據(jù)準備好過后才處理其他的事情,否則一直等待
在那里。- eg:SeverSocket 中的accept() 。
- 非阻塞(Non-Block):進程訪問數(shù)據(jù)緩沖區(qū)的時候,如果數(shù)據(jù)沒有準備好則直接返回,
不會等待
。如果數(shù)據(jù)已經(jīng)準備好,也直接返回。- nio 中的Selector 。
1.2、阻塞IO(Block IO)與非阻塞IO(Non-Block IO) 圖解:
2、同步IO (Syn IO)與異步IO (Asyn IO)
2.1、同步IO(Syn IO)和異步IO(Asyn IO)的對比:
同步和異步都是基于服務端
處理請求采用的方式:
- eg:
- 同步(Synchronization):client發(fā)出請求到服務端,無論服務端是否阻塞以及其他情況,只要
服務端同步返回結(jié)果
,就認定是同步。 - 異步(Asynchronous):client發(fā)出請求到服務端,同步返回值中沒有結(jié)果,Client只需要
等待通知
,收到通知后才能拉取結(jié)果,就是異步。
- 同步(Synchronization):client發(fā)出請求到服務端,無論服務端是否阻塞以及其他情況,只要
2.2、同步IO和異步IO還是比較抽象的,繼續(xù)類比:
- 同步IO,可以類比客戶端與服務端通信方式采用RPC方式,同步給返回結(jié)果。
- 異步IO,可以類比客戶端與服務端通信方式采用MQ+RPC方式,異步給客戶端一個通知,Client端再通過RPC同步返回結(jié)果。
2.3、同步IO和異步IO 類比生活中貨車拉貨:
3、BIO、NIO、AIO
3.1、Java BIO(Block IO)和 NIO(Non-Block IO)之間的主要差別異:
IO模型 | BIO | NIO |
---|---|---|
通信 | 面向流 | 面向緩沖區(qū)(多路復用技術(shù)) |
處理 | 阻塞IO(多線程) | 非阻塞IO(反應堆Reactor) |
觸發(fā) | 無 | 選擇器(輪詢機制) |
-
3.2、對比之面向流與面向緩沖區(qū)
Java NIO 和 BIO 之間第一個最大的區(qū)別是,BIO 是面向流
的,NIO 是面向緩沖區(qū)
的。
Java BIO 面向流意味著每次從流中讀一個或多個字節(jié),直至讀取所有字節(jié),它們沒有被緩存在任何地方。此外,它不能前后移動流中的數(shù)據(jù)。 如果需要前后移動從流中讀取的數(shù)據(jù),需要先將它緩存到一個緩沖區(qū)。
Java NIO 面向緩沖區(qū)導向方法略有不同。數(shù)據(jù)讀取到一個它稍后處理的緩沖區(qū),需要時可在緩沖區(qū)中前后移動。這就增加了處理過程中的靈活性。
-
3.3、對比之阻塞與非阻塞
Java BIO 的各種流是阻塞的。這意味著,當一個線程調(diào)用 read() 或 write()時,該線程被阻塞,直到有一些數(shù)據(jù)被讀取,或數(shù)據(jù)完全寫入。該線程在此期間不能再干任何事情了。
Java NIO 的非阻塞模式,使一個線程【boss線程】從某通道發(fā)送請求讀取數(shù)據(jù),但是它僅能得到目前可用的數(shù)據(jù),如果目前沒有數(shù)據(jù)可用時,就什么都不會獲取,而不是保持線程阻塞, 所以直至數(shù)據(jù)變的可以讀取之前,該線程可以繼續(xù)做其他的事情。 非阻塞寫也是如此。一個線程請求寫入一些數(shù)據(jù)到某通道,但不需要等待它完全寫入,這個線程同時可以去做別的事情。 線程通常將非阻塞 IO 的空閑時間用于在其它通道上執(zhí)行 IO 操作,所以一個單獨的線程現(xiàn)【boss線程】在可以管理多個輸入和輸出通道(channel)。
-
3.4、selector選擇器問世
Java NIO 的選擇器(Selector)允許一個單獨的線程來監(jiān)視多個輸入通道,你可以注冊多個通道使用一個選擇器,然后使用一個單獨的線程來選擇通道:這些通道里已經(jīng)有可以處理的輸入,或者選擇已準備寫入的通道。這種選擇機制, 使得一個單獨的線程很容易來管理多個通道。
-
3.5、NIO 和 BIO 讀取磁盤數(shù)據(jù)的對比
-
3.5.1、java BIO模式讀取磁盤數(shù)據(jù):
-
/**
* @description: java 阻塞IO從磁盤讀取txt文件
**/
public class ReadTxtDemo {
private static String fileName="/xxxx/io/bio/txt/source.txt";
public static void main(String[] args) throws IOException {
readTxtFile(fileName);
}
private static void readTxtFile(String fileName) throws IOException {
FileInputStream input = new FileInputStream(fileName);
BufferedReader reader = new BufferedReader(new InputStreamReader(input));
while (true) {
String str = reader.readLine();
if(str!=null)
System.out.println(str);
else
break;
}
reader.close();
input.close();
}
}
控制臺輸出:
name:biudefu
age:18
email:biudefu@qq.com
phone:18666666666
Process finished with exit code 0
-
3.5.2、java NIO模式讀取磁盤數(shù)據(jù):
/**
* @description: java 非阻塞IO,nio方式,讀取磁盤文件
**/
public class NioReadTxtDemo {
private static String fileName="/xxxx/txt/source.txt";
public static void main(String[] args) throws IOException {
readTxtFile(fileName);
}
private static void readTxtFile(String fileName) throws IOException {
FileInputStream f1 = new FileInputStream(fileName);
FileChannel channel = f1.getChannel();
ByteBuffer b1 = ByteBuffer.allocate(8);//初始化緩沖區(qū)大小
int length ;
while ((length = channel.read(b1)) != -1) {
b1.clear();
byte[] bytes = b1.array();
System.out.write(bytes, 0, length);
}
channel.close();
}
}
控制臺輸出:
name:biudefu
age:18
email:biudefu@qq.com
phone:18666666666
Process finished with exit code 0
-
3.6、BIO、NIO、AIO應用場景
屬性 | 同步阻塞IO | 偽異步IO | 非阻塞IO(NIO) | 異步IO(AIO) |
---|---|---|---|---|
阻塞類型 | 阻塞 | 阻塞 | 非阻塞 | 非阻塞 |
同步類型 | 同步 | 同步 | 同步(多路復用) | 異步 |
API使用難度 | 簡單 | 簡單 | 復雜 | 一般 |
調(diào)試難度 | 簡單 | 簡單 | 復雜 | 復雜 |
可靠性 | 非常差 | 差 | 高 | 高 |
吞吐量 | 低 | 中 | 高 | 高 |
4、Unix網(wǎng)絡編程5種I/O模型 !!!!!圖有問題需要修改!!!!!!
-
4.1、阻塞I/O(準備數(shù)據(jù)+復制數(shù)據(jù)均是阻塞)(
同步阻塞IO
)
-
4.2、非阻塞I/O(準備數(shù)據(jù)非阻塞,復制數(shù)據(jù)阻塞)(
同步非阻塞IO
)
-
4.3、多路復用I/O(準備數(shù)據(jù)+復制數(shù)據(jù)均是阻塞)(
同步非阻塞IO
)
-
4.4、信號驅(qū)動I/O(準備數(shù)據(jù)非阻塞,復制數(shù)據(jù)阻塞)(
異步非阻塞IO
)
-
4.5、異步I/O(準備數(shù)據(jù)+復制數(shù)據(jù)均是非阻塞)(
異步非阻塞IO
)
5、面試常見問題
-
5.1、流按照傳輸?shù)姆较蛟趺捶诸悾?/h6>
相對于內(nèi)存
來說,流按照傳輸方向,可以分為輸入流InputStream、輸出流OutputStream。
-
5.2、流按照傳輸?shù)膯挝辉趺捶诸悾糠殖赡膬煞N流,并且他們的父類叫什么?說一下常用的IO流?
流按照傳輸單位分為 字節(jié)流 和 字符流
字節(jié)流的抽象基類(父類)是:java.io.InputStream、java.io.OutputStream
字符流的抽象基類(父類)是:java.io.Reader 、java.io.Writer
-
5.3、流按實現(xiàn)功能怎么分?
按照功能分為:節(jié)點流 OutputStream、處理流 OutputStreamWriter
節(jié)點流 :直接與數(shù)據(jù)源(文件等)相連,用于輸入或輸出。
處理流:在節(jié)點流的基礎上對之進行加工,進行一些功能的擴展。
處理流的構(gòu)造器必須要 傳入節(jié)點流的子類。
-
5.4、FileInputStream和FileOutputStream 與 BufferedInputStream 和 BufferedOutputStream區(qū)別?
這是在拷貝文件操作的時候,經(jīng)常用到的兩個類。在處理小文件的時候,F(xiàn)ileInputStream和FileOutputStream性能表現(xiàn)還不錯,在大文件的時候,最好使用BufferedInputStream(或BufferedReader)和BufferedOutputStream(或BufferedWriter)。
-
5.5、flush() 方法的作用?
flush()方法可以強迫輸出流(或緩沖的流)發(fā)送數(shù)據(jù),即使此時緩沖區(qū)還沒有填滿,以此來打破這種死鎖的狀態(tài)。
-
5.6、什么是同步阻塞IO,什么是同步非阻塞IO,什么是異步阻塞IO?什么是異步非阻塞IO?
- 同步阻塞IO:丟衣服->站在洗衣機前面,直到洗衣機洗完->再去晾衣服。
- 同步非阻塞IO:丟衣服->去做其他事情,定時去看衣服是否洗完->洗完后自己去晾衣服。
- 異步阻塞IO:丟衣服-> 站在洗衣機前面,直到洗衣機洗完,洗衣機會發(fā)出聲響
通知你
->再去晾衣服。 - 異步非阻塞IO:丟衣服-> 去做其他事情,衣服洗好會自動晾好,并且發(fā)出聲音
通知你
晾好了。
tips:同步&異步是指洗衣機會不會通知你。阻塞&非阻塞是指在洗衣服期間你還可不可以干別的?
-
5.6、IO模型有幾種?分別是什么?
- 阻塞 IO、非阻塞 IO、多路復用 IO、信號驅(qū)動 IO、異步 IO,其中前三種是同步,且內(nèi)核數(shù)據(jù) copy 到用戶空間時是阻塞的。
- 如上圖IO五種模式。
-
5.7、五種IO模型在java中是如何支持的?
- 同步阻塞IO:BIO中 當沒有請求 or 沒有響應(socket.accept()、socket.read()、socket.write()方法)函數(shù)無法進行有效的中斷。
- 同步非阻塞IO(多路復用IO):NIO中 java.nio.channels.ServerSocketChannel 中的accept()等讀寫函數(shù)可以立刻返回。
- 異步非阻塞IO:AIO中的java.nio.channels.AsynchronousServerSocketChannel 中的accept()方法。