Java編程語言中,有兩個常見的I/O操作方式:阻塞I/O (Blocking IO, BIO) 和非阻塞I/O(Non-blocking IO, NIO)。此篇文章將比較它們的特點及區別。
BIO(阻塞I/O)
try(ServerSocket serverSocket = new ServerSocket(8080)) { while (true) { // 一直等待客戶端的連接 Socket socket = serverSocket.accept(); // 對連接進行處理 processSocket(socket); } } catch IOException e) { e.printStackTrace(); }
在BIO中,一個線程處理一個I/O任務,當任務沒有被處理時,這個線程將一直阻塞等待。這就意味著任何一個新的I/O請求都必須創建一個新線程來處理。當有大量并發請求時,會導致大量的線程被創建,消耗大量資源。
NIO(非阻塞I/O)
Selector selector = Selector.open(); ServerSocketChannel serverSocket = ServerSocketChannel.open(); serverSocket.bind(new InetSocketAddress(8080)); serverSocket.configureBlocking(false); serverSocket.register(selector, SelectionKey.OP_ACCEPT); while (true) { selector.select(); Set<SelectionKey> selectionKeys = selector.selectedKeys(); for (SelectionKey key : selectionKeys) { if (key.isAcceptable()) { ServerSocketChannel server = (ServerSocketChannel) key.channel(); SocketChannel client = server.accept(); client.configureBlocking(false); client.register(selector, SelectionKey.OP_READ); } else if (key.isReadable()) { SocketChannel client = (SocketChannel) key.channel(); // 處理讀取操作 processRead(client); } selectionKeys.remove(key); } }
NIO基于事件驅動模型,當I/O請求被觸發時,其對應的線程便立即被喚醒處理。在NIO中,一個線程可以處理多個I/O任務,當任務不存在時,線程可進行其它操作。這使得NIO在高并發請求下更加高效。
NIO與BIO的對比
通過上述代碼,可以看出,NIO與BIO之間有以下幾個重要的區別:
- NIO是非阻塞的,能夠處理同時進行多個任務
- NIO使用Selector來處理可讀寫事件,而BIO直接使用Socket進行處理
- BIO在I/O請求未到達時會一直阻塞,但NIO會返回null
在高并發量的情況下,NIO的效率要比BIO高。而在低并發或I/O負載非常低時,BIO比NIO更為簡單易用。
下一篇jquery+判斷電話