一、NIO Selector的定義和作用
Java NIO(New IO)是從Java 1.4版本開始引入的,用於替代原來的Java IO API,NIO提供了一種面向緩衝區的、基於通道的I/O操作方式。NIO中的Selector其實是一個選擇器,用於處理多個通道的選擇性IO操作。以前,一個線程只能處理一個連接,而Selector提供了一種可以通過一個線程處理多個連接的方式。
在使用NIO編程時,Selector負責監控被註冊進它裡面的Channel,當Channel中有可以進行IO操作的狀態時,Selector將會得到通知,進行相應的處理,而不需要線程一直輪詢。因此,NIO Selector解決了Java BIO的瓶頸問題,保證了處理高並發連接時系統性能和可靠性的平衡。
二、NIO Selector的基本使用方法
下面給出一個簡單的例子來說明如何使用NIO Selector實現服務端與客戶端的簡單通信:
Selector selector = Selector.open(); ServerSocketChannel serverSocket = ServerSocketChannel.open(); serverSocket.bind(new InetSocketAddress(8080)); serverSocket.configureBlocking(false); SelectionKey selectionKey = serverSocket.register(selector, SelectionKey.OP_ACCEPT); while (true) { selector.select(); Set<SelectionKey> selectionKeys = selector.selectedKeys(); Iterator<SelectionKey> iterator = selectionKeys.iterator(); while (iterator.hasNext()) { SelectionKey key = iterator.next(); if (key.isAcceptable()) { ServerSocketChannel serverSocketChannel = (ServerSocketChannel) key.channel(); SocketChannel socketChannel = serverSocketChannel.accept(); socketChannel.configureBlocking(false); socketChannel.register(selector, SelectionKey.OP_READ); System.out.println("建立鏈接"); } else if (key.isReadable()) { SocketChannel socketChannel = (SocketChannel) key.channel(); ByteBuffer buffer = ByteBuffer.allocate(1024); socketChannel.read(buffer); String receive = new String(buffer.array()); System.out.println("接收到客戶端的信息:" + receive); } iterator.remove(); } }
上述代碼中,我們首先創建一個Selector實例並打開一個ServerSocketChannel,然後將ServerSocketChannel註冊到Selector上,並且聲明該Selector對客戶端連接請求(OP_ACCEPT)感興趣。
最後通過不斷地輪詢select()方法,來檢查是否有連接已經準備好進行I/O操作。在select()方法返回之後,我們通過迭代器獲取可操作的SelectionKey集合,然後進行相應操作,例如建立連接或者從通道中讀取數據。
三、NIO Selector的優缺點
NIO Selector有以下幾個優點:
1、單線程可以處理多個連接,降低了系統開銷,提高了系統的伸縮性;
2、為非阻塞I/O提供了一個優良的基礎,Selector監聽多個Channel的I/O事件的能力使得單個線程可以處理多個並發通道,從而提高了系統的並發處理能力;
3、提供了更高效的事件通知機制。當向Selector註冊Channel時,可以指定我們感興趣的操作類型(Connect、Accept、Read、Write),只有在這些事件發生時,Selector才會返回,否則就一直阻塞。這樣,我們就可以用一個線程去管理多個channel,也就是NIO實現高效的處理方式的基礎;
但同時,NIO Selector也有以下幾個缺點:
1、對於連接的管理較為複雜,且處理細節需要高度注意;
2、編程較為繁瑣,需要一定的經驗和能力;
3、自己編寫網絡框架時,使用NIO Selector需要考慮到眾多細節問題,涉及到多線程、使用ByteBuffer等方面;
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/286804.html