在對本文的問題進行分析之前,我們先看下同步異步,阻塞非則塞者兩對概念。
(1)同步和異步
同步和異步描述的是一種消息通知的機制,主動等待消息返回還是被動接受消息。同步io指的是調用方通過主動等待獲取調用返回的結果來獲取消息通知,而異步io指的是被調用方通過某種方式(如,回調函數)來通知調用方獲取消息。
(2)阻塞非阻塞
阻塞和非阻塞描述的是調用方在獲取消息過程中的狀態,阻塞等待還是立刻返回。阻塞io指的是調用方在獲取消息的過程中會掛起阻塞,知道獲取到消息,而非阻塞io指的是調用方在獲取io的過程中會立刻返回而不進行掛起。
BIO(Blocking IO)阻塞IO
NIO(Non-Blocking IO)非阻塞IO
共同點:兩者都是同步操作。即必須先進行IO操作後才能進行下一步操作。
不同點:BIO多線程對某資源進行IO操作時會出現阻塞,即一個線程進行IO操作完纔會通知另外的IO操作線程,必須等待。
NIO多線程對某資源進行IO操作時會把資源先操作至內存緩衝區。然後詢問是否IO操作就緒,是則進行IO操作,否則進行下一步操作,然後不斷的輪詢是否IO操作就緒,直到iIO操作就緒後進行相關操作。
爲什麼java nio是同步非阻塞的?
我們知道java nio是基於io多路複用模型,也就是我們經常提到的select,poll,epoll。io 多路複用本質是同步io,其需要調用方在讀寫事件就緒時主動去進行讀寫。在java nio中,通過selector來獲取就緒的事件,當selector上監聽的channel中沒有就緒的讀寫時間時,其可以直接返回,或者設置一段超時後返回。可以看出java nio可以實現非則塞,而不像傳統io裏必須則塞當前線程直到可讀或可寫。所以,java nio可以實現非阻塞。我們簡單看下java nio處理連接和java socket 處理連接的方式:
//java nio
while(true) {
......
selector.select(1);
Set<SelectionKey> selectionKeySet= selector.selectedKeys();
......
//處理selectionKeySet中事件,線程沒有阻塞
}
//java socket處理連接,線程會阻塞
while(true) {
......
Socket socket = serverSocket.accept();
InputStream in = socket.getInputStream();
......
//處理in中內容
}