引言:本文將深入探討這些I/O操作的核心概念,透過生活中的比喻,將抽象的技術術語轉化為易於理解的日常場景。我們將一起探索同步與異步的通訊機制,理解它們如何在不同的情境下發揮作用,以及阻塞與非阻塞如何影響程式的執行流程。透過這些深入淺出的解析,我們希望能夠幫助讀者更好地理解I/O操作的本質,從而在編程實踐中做出更明智的選擇。
題目
同步、異步、阻塞、非阻塞的IO的區別?
推薦解析
同步和異步概念
同步和異步關註的是訊息通訊機制。
同步,就是在發出一個呼叫時,在沒有得到結果之前,該呼叫就不返回。但是一旦呼叫返回,就得到返回值了。
異步則是相反,呼叫在發出之後,這個呼叫就直接返回了,所以沒有返回結果。
生活舉例
同步:在人工咖啡店點咖啡,排隊等待服務員制作完成,等制作完成之後,才能進行下一步行動。
異步:自助咖啡機等咖啡,可以在等咖啡時做其他事情,例如玩手機,讀雜誌。
同步的舉例很明顯現在已經被最佳化了,因為同步的對人為感覺明顯不好,異步更為舒適。
阻塞和非阻塞概念
阻塞和非阻塞關註程式在等待呼叫結果時的狀態。
阻塞:被呼叫者接受到任務請求,會掛起當前執行緒,執行任務請求,直到完成,然後返回給呼叫者。
非阻塞:被呼叫者,先做完其他的事情,然後開始做呼叫者的任務請求,不會阻塞當前執行緒。
生活舉例
阻塞:交通擁堵的交通路口等待紅綠燈,只有交通訊號燈變綠才能繼續前行,車輛被阻塞。
非阻塞:當你在等待電梯,此時電梯在其他樓層,采用非阻塞方式,可以采用樓梯代替電梯。
Java 程式碼舉例
同步阻塞I/O(BIO)
import java.io.FileInputStream;
import java.io.IOException;
public classSyncBlockingIOExample{
publicstaticvoidmain(String[] args){
try (FileInputStream fis = new FileInputStream("example.txt")) {
int data;
while ((data = fis.read()) != -1) {
// 處理數據
System.out.print((char) data);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
同步非阻塞I/O
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
public classSyncNonBlockingIOExample{
publicstaticvoidmain(String[] args)throws Exception {
FileChannel channel = FileChannel.open(Paths.get("example.txt"), StandardOpenOption.READ);
ByteBuffer buffer = ByteBuffer.allocate(1024);
while (channel.read(buffer) != -1) {
buffer.flip();
while (buffer.hasRemaining()) {
// 處理數據
System.out.print((char) buffer.get());
}
buffer.clear();
}
channel.close();
}
}
異步I/O(AIO)
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousFileChannel;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.concurrent.Future;
public classAsyncIOExample{
publicstaticvoidmain(String[] args)throws Exception {
AsynchronousFileChannel channel = AsynchronousFileChannel.open(Paths.get("example.txt"), StandardOpenOption.READ);
ByteBuffer buffer = ByteBuffer.allocate(1024);
Future<Integer> result = channel.read(buffer, 0);
while (!result.isDone()) {
// 執行其他任務
}
buffer.flip();
while (buffer.hasRemaining()) {
// 處理數據
System.out.print((char) buffer.get());
}
buffer.clear();
channel.close();
}
}
區別詳解
同步I/O
1) 定義 :同步I/O是指程式發起一個I/O操作後,必須等待該操作完成並獲取到結果後,才能繼續執行後續程式碼。
2) 特點 :同步I/O操作會阻塞程式的執行,直到I/O操作完成。這意味著程式在等待I/O操作期間不能執行其他任務。
3)
範例
:在Java中,使用
java.io
包中的
FileInputStream
或
FileOutputStream
進行檔讀寫就是同步I/O的例子。
異步I/O
1) 定義 :異步I/O是指程式發起一個I/O操作後,不需要等待該操作完成,而是可以繼續執行後續程式碼。I/O操作完成後,程式會透過回呼、事件或輪詢等方式得到通知。
2) 特點 :異步I/O不會阻塞程式的執行,允許程式在I/O操作進行的同時執行其他任務,提高了程式的並行性和效率。
3)
範例
:在Java中,使用
java.nio.channels.AsynchronousFileChannel
進行檔讀寫就是異步I/O的例子。
阻塞I/O
1) 定義 :阻塞I/O是指程式發起一個I/O操作後,如果數據尚未準備好(如數據未到達、檔未找到等),程式會一直等待,直到數據準備好並完成I/O操作。
2) 特點 :阻塞I/O會導致程式的執行執行緒被掛起,直到I/O操作完成。在這期間,執行緒不能執行其他任務。
3)
範例
:在Java中,使用
java.io
包中的
Socket
進行網路通訊時,
InputStream.read()
方法就是阻塞I/O的例子。
非阻塞I/O
1) 定義 :非阻塞I/O是指程式發起一個I/O操作後,如果數據尚未準備好,I/O操作會立即返回一個錯誤或特定值,而不是等待數據準備好。
2) 特點 :非阻塞I/O允許程式在數據未準備好時繼續執行其他任務,而不是等待。程式通常需要輪詢或檢查I/O操作的狀態,以確定何時數據準備好。
3)
範例
:在Java中,使用
java.nio
包中的
SocketChannel
設定為非阻塞模式,並使用
read()
方法進行網路通訊,就是非阻塞I/O的例子。
其他補充
魚聰明 AI 的回答:
魚聰明 AI 地址:https://www.yucongming.com/
同步IO:當程式發起IO操作時,程式會一直等待IO操作完成後才能繼續執行後續操作,這種IO稱為同步IO。
異步IO:程式發起IO操作後,不需要等待IO操作完成,而是繼續執行後續操作,當IO操作完成後透過回呼等方式通知程式,這種IO稱為異步IO。
阻塞IO:程式發起IO操作時,如果IO操作無法立即完成,程式會一直等待IO操作完成或出錯後才能繼續執行後續操作,這種IO稱為阻塞IO。
非阻塞IO:程式發起IO操作時,如果IO操作無法立即完成,程式會立即返回一個錯誤碼或結果,然後繼續執行後續操作,透過輪詢等方式可以判斷IO操作是否完成,這種IO稱為非阻塞IO。
總結:
同步IO和異步IO是根據程式等待IO操作完成的方式來區分的。
阻塞IO和非阻塞IO是根據程式在等待IO操作完成時是否能繼續執行其他操作來區分的。
歡迎交流
閱讀完本文,你應該對 IO 三種模型,Java 如何使用 IO 進行讀取,有了一定的了解,本文是面試的重點問題之一,需要重點學習,在文末還有三個問題,歡迎小夥伴在評論區留言!
1)在實際的編程套用中,你更傾向於使用同步IO還是異步IO?為什麽?
2)阻塞IO和非阻塞IO在網路編程中有何區別?你在開發網路套用時如何選擇適合的IO模型?
3)在並行編程中,如何處理IO操作的效能問題?有沒有什麽最佳化策略可以提升IO操作的效率?
點燃求職熱情!每周持續更新,海量面試題和大廠面經等你挑戰!趕緊關註面試鴨公眾號,輕松備戰春招和暑期實習!
往期推薦