IO全稱為輸入/輸出(Input/Output,正規(guī)簡稱I/O),指的是計算機系統(tǒng)與外部設(shè)備之間的數(shù)據(jù)交換。外部設(shè)備包括輸入設(shè)備(如鼠標、鍵盤等)、輸出設(shè)備(如顯示器)、存儲設(shè)備(如硬盤)和網(wǎng)絡(luò)設(shè)備等。
傳統(tǒng)的I/O操作是阻塞的,這意味著當一個I/O操作進行時,當前的執(zhí)行體會被掛起,進入等待狀態(tài),直到I/O結(jié)果返回,執(zhí)行體才會繼續(xù)處理后續(xù)的邏輯。這就像你去圖書館前臺借一本非常熱門的書,但書已經(jīng)被借出。為了得到這本書,你選擇站在前臺等待,直到這本書被歸還。等待的過程中,你不能去干其它任何事情。
非阻塞I/O更像是這樣:你去借那本熱門書籍,但被告知現(xiàn)在沒有。這時,你留下聯(lián)系方式并告訴圖書管理員,一旦書歸還,請通知你。然后你可以自由地去參加其他活動。
在借書的這個例子中,你不用浪費大量的時間在等待上,同樣的時間你可以做更多的事,可以說,非阻塞I/O極大的提高了系統(tǒng)運行效率。另外還有很多同學說非阻塞IO快,阻塞IO慢,真的是這樣嗎?
本文,我們將深入探討阻塞I/O遇到的問題,非阻塞I/O的原理、優(yōu)勢及其實現(xiàn)方法,幫助大家更好地理解和應(yīng)用這一技術(shù)。
阻塞IO為什么被詬?。?span style="display:none">kqD28資訊網(wǎng)——每日最新資訊28at.com
在高并發(fā)場景下,如果使用阻塞I/O模型,每個請求都需要創(chuàng)建一個新的線程來處理。當這些請求中有大量操作處于I/O等待狀態(tài)時,雖然CPU能夠切換到其他任務(wù)繼續(xù)執(zhí)行,但創(chuàng)建和管理大量線程本身也會消耗系統(tǒng)資源,包括內(nèi)存和用于線程上下文切換的CPU時間,從而影響系統(tǒng)的整體性能和可擴展性。
正如上面借書的例子,當IO操作發(fā)生時,我們無需等待,可以去干別的事,只有IO操作返回時,我們才需要處理IO返回的結(jié)果,這就是非阻塞IO的本質(zhì)。
非阻塞IO可以解決阻塞IO的內(nèi)存占用過大和上下文切換頻繁問題,下邊我將介紹幾個典型的非阻塞IO模型,方便大家理解其中的原理。
Java NIO(New I/O)引入了非阻塞I/O機制,通過Channel和Buffer來處理數(shù)據(jù),使用Selector來管理多個Channel。
import java.io.IOException;import java.nio.ByteBuffer;import java.nio.channels.SelectionKey;import java.nio.channels.Selector;import java.nio.channels.ServerSocketChannel;import java.nio.channels.SocketChannel;import java.net.InetSocketAddress;import java.util.Iterator;public class NIOServer { public static void main(String[] args) throws IOException { Selector selector = Selector.open(); ServerSocketChannel serverSocket = ServerSocketChannel.open(); serverSocket.bind(new InetSocketAddress("localhost", 8080)); serverSocket.configureBlocking(false); serverSocket.register(selector, SelectionKey.OP_ACCEPT); while (true) { selector.select(); Iterator<SelectionKey> keys = selector.selectedKeys().iterator(); while (keys.hasNext()) { SelectionKey key = keys.next(); keys.remove(); if (key.isAcceptable()) { SocketChannel client = serverSocket.accept(); client.configureBlocking(false); client.register(selector, SelectionKey.OP_READ); } else if (key.isReadable()) { SocketChannel client = (SocketChannel) key.channel(); ByteBuffer buffer = ByteBuffer.allocate(256); client.read(buffer); System.out.println("Received: " + new String(buffer.array()).trim()); } } } }}
asyncio是Python標準庫中的一個庫,提供了異步I/O支持。它基于事件循環(huán)(event loop),可以調(diào)度和執(zhí)行異步任務(wù)(coroutines)。
import asyncioasync def handle_client(reader, writer): data = await reader.read(100) message = data.decode() print(f"Received: {message}") writer.write(data) await writer.drain() writer.close()async def main(): server = await asyncio.start_server(handle_client, '127.0.0.1', 8888) async with server: await server.serve_forever()asyncio.run(main())
圖片
Node.js使用事件驅(qū)動模型和非阻塞I/O操作,基于libuv庫實現(xiàn)。libuv是一個跨平臺的異步I/O庫,封裝了不同操作系統(tǒng)的I/O多路復(fù)用機制(如epoll、kqueue、IOCP等)。
const http = require('http');const server = http.createServer((req, res) => { if (req.method === 'GET') { res.writeHead(200, { 'Content-Type': 'text/plain' }); res.end('Hello, World!/n'); }});server.listen(8080, '127.0.0.1', () => { console.log('Server running at http://127.0.0.1:8080/');});
圖片
Go語言通過goroutine和channel提供了輕量級的并發(fā)支持。goroutine是Go語言中的輕量級線程,或者也叫協(xié)程,通過channel進行通信和同步。select語句用于監(jiān)聽多個channel的操作,實現(xiàn)非阻塞I/O。
package mainimport ( "fmt" "net" "bufio")func handleConnection(conn net.Conn) { defer conn.Close() reader := bufio.NewReader(conn) for { message, _ := reader.ReadString('/n') fmt.Printf("Received: %s", message) conn.Write([]byte(message)) }}func main() { listener, _ := net.Listen("tcp", "localhost:8080") defer listener.Close() for { conn, _ := listener.Accept() go handleConnection(conn) }}
對于單次IO,從發(fā)起到收到響應(yīng),其中主要有三段時間:請求數(shù)據(jù)從客戶端到服務(wù)端的傳輸時間、服務(wù)端的處理時間、響應(yīng)數(shù)據(jù)從服務(wù)端到客戶端的返回時間。對于這三段時間,非阻塞IO和阻塞IO都沒有任何影響力或者說影響甚小,它們都不會因為使用非阻塞IO而變的更快。
但是非阻塞IO因為更優(yōu)的內(nèi)存使用效率,服務(wù)器可以支撐更大的并發(fā)訪問,在繁忙的系統(tǒng)中,如果存在因為內(nèi)存分配或者線程調(diào)度而導(dǎo)致請求接入等待的情況,非阻塞IO一定程度上會降低請求接入的平均時間,從而讓服務(wù)端的處理更快一些。不過這是非阻塞IO結(jié)合協(xié)程機制的效果,單純非阻塞IO沒有這個能力。
以上就是本文的主要內(nèi)容。非阻塞I/O通過更高效的資源利用和更低的線程管理開銷,顯著提升了系統(tǒng)在高并發(fā)場景下的性能和擴展性。盡管它不能直接加快單次I/O操作的速度,但其在整體性能優(yōu)化方面的優(yōu)勢使其成為現(xiàn)代軟件系統(tǒng)中不可或缺的重要部分。掌握非阻塞I/O技術(shù),對于開發(fā)高性能、高可擴展性的應(yīng)用至關(guān)重要。希望本文能幫助大家更好地理解和應(yīng)用這一技術(shù)。
本文鏈接:http://www.www897cc.com/showinfo-26-94847-0.html為什么高手都要用非阻塞IO?
聲明:本網(wǎng)頁內(nèi)容旨在傳播知識,若有侵權(quán)等問題請及時與本網(wǎng)聯(lián)系,我們將在第一時間刪除處理。郵件:2376512515@qq.com