在本課中,我們將熟悉Selector類。此類位於java.nio.channels包中,因此您無需下載或配置任何內容即可使用它。選擇對象可以監視一個或多個通道對象,檢查它們是否準備好讀/寫等。最重要的是,選擇器需要一個流,而不是每個通道一個流。

我們使用靜態打開方法創建選擇器:


Selector selector = Selector.open();

之後,可以在選擇器對像中註冊通道:


SelectionKey key1 = channel1.register(selector, SelectionKey.OP_READ);
SelectionKey key2 = channel2.register(selector, SelectionKey.OP_WRITE);

register方法的第二個參數確定選擇器將監視哪個操作。如果需要同時監控多個操作,可以使用按位或:


SelectionKey.OP_READ | SelectionKey.OP_WRITE

當任何通道上發生 I/O 操作時,選擇器都會通知我們。例如,您可以通過這種方式從大量數據源中讀取數據。

這裡我們需要提到的是,通道必須處於非阻塞模式才能與選擇器一起使用:


channel1.configureBlocking(false);
channel2.configureBlocking(false);
SelectionKey key1 = channel1.register(selector, SelectionKey.OP_READ);
SelectionKey key2 = channel2.register(selector, SelectionKey.OP_WRITE);

因此選擇器不能與FileChannel一起工作,因為FileChannel不能切換到非阻塞模式(configureBlocking方法在SelectableChannel類中聲明,FileChannel不繼承)。

從圖中可以看出,選擇器適合與套接字一起使用。我們將在第二個模塊結束時與他們合作。

選擇鍵

使用選擇器註冊頻道時,我們會得到一個選擇鍵目的。該對象包含有關頻道註冊的數據。

您可以使用 key 來確定通道是否準備好接受某個值:


key.isReadable()
key.isAcceptable()
key.isConnectable()
key.isWritable()

key可以給你對應的channel和selector:


Channel channel = key.channel();
Selector selector = key.selector();

您可以將任何對象附加到密鑰,以便將來跟踪它。這可以在頻道註冊期間(通過第三個參數)或之後完成:

  1. SelectionKey key = channel.register(selector, SelectionKey.OP_ACCEPT, object);

  2. 鍵.附加(對象);

稍後,您可以從鍵中獲取附加對象:


Object object = key.attachment();

結論

使用選擇器註冊頻道後,我們可以:

  • 找出準備執行指定操作的通道數
  • 阻止我們程序的執行,直到至少一個通道準備就緒
  • 為就緒頻道獲取一組密鑰
  • 和更多

在第二個模塊的末尾,我們將在實踐中試用選擇器。