JavaTM 2 Platform
Standard Ed. 6

java.nio.channels
類別 Selector

java.lang.Object
  繼承者 java.nio.channels.Selector
直接已知子類別:
AbstractSelector

public abstract class Selector
extends Object

SelectableChannel 物件的多路傳輸器。

可通過調用此類別的 open 方法創建選擇器,該方法將使用系統的預設選擇器提供者創建新的選擇器。也可通過調用自定義選擇器提供者的 openSelector 方法來創建選擇器。通過選擇器的 close 方法關閉選擇器之前,它一直保持打開狀態。

通過 SelectionKey 物件來表示可選擇通道到選擇器的註冊。選擇器維護了三種選擇鍵集:

在新創建的選擇器中,這三個集合都是空集合。

通過某個通道的 register 方法註冊該通道時,所帶來的副作用是向選擇器的鍵集中添加了一個鍵。在選擇操作期間從鍵集中移除已取消的鍵。鍵集本身是不可直接修改的。

不管是通過關閉某個鍵的通道還是調用該鍵的 cancel 方法來取消鍵,該鍵都被添加到其選擇器的已取消鍵集中。取消某個鍵會導致在下一次選擇操作期間註銷該鍵的通道,而在註銷時將從所有選擇器的鍵集中移除該鍵。

通過選擇操作將鍵添加到已選擇鍵集中。可通過調用已選擇鍵集的 remove 方法,或者通過調用從該鍵集獲得的 iteratorremove 方法直接移除某個鍵。通過任何其他方式從不會將鍵從已選擇鍵集中移除;特別是,它們不會因為影響選擇操作而被移除。不能將鍵直接添加到已選擇鍵集中。

選擇

在每次選擇操作期間,都可以將鍵添加到選擇器的已選擇鍵集以及從中將其移除,並且可以從其鍵集和已取消鍵集中將其移除。選擇是由 select()select(long)selectNow() 方法執行的,執行涉及三個步驟:

  1. 將已取消鍵集中的每個鍵從所有鍵集中移除(如果該鍵是鍵集的成員),並註銷其通道。此步驟使已取消鍵集成為空集。

  2. 在開始進行選擇操作時,應查詢基礎作業系統來更新每個剩餘通道的準備就緒資訊,以執行由其鍵的相關集合所標識的任意操作。對於已為至少一個這樣的操作準備就緒的通道,執行以下兩種操作之一:

    1. 如果該通道的鍵尚未在已選擇鍵集中,則將其添加到該集合中,並修改其準備就緒操作集,以準確地標識那些通道現在已報告為之準備就緒的操作。丟棄準備就緒操作集中以前記錄的所有準備就緒資訊。

    2. 如果該通道的鍵已經在已選擇鍵集中,則修改其準備就緒操作集,以準確地標識所有通道已報告為之準備就緒的新操作。保留準備就緒操作集以前記錄的所有準備就緒資訊;換句話說,基礎系統所返回的準備就緒操作集是和該鍵的當前準備就緒操作集按位分開 (bitwise-disjoined) 的。

  3. 如果在此步驟開始時鍵集中的所有鍵都有空的相關集合,則不會更新已選擇鍵集和任意鍵的準備就緒操作集。
  4. 如果在步驟 (2) 的執行過程中要將任意鍵添加到已取消鍵集中,則處理過程如步驟 (1)。

是否阻塞選擇操作以等待一個或多個通道準備就緒,如果這樣做的話,要等待多久,這是三種選擇方法之間的唯一本質差別。

共時性

選擇器自身可由多個共時執行緒安全使用,但是其鍵集並非如此。

選擇操作在選擇器本身上、在鍵集上和在已選擇鍵集上是同步的,順序也與此順序相同。在執行上面的步驟 (1) 和 (3) 時,它們在已取消鍵集上也是同步的。

在執行選擇操作的過程中,更改選擇器鍵的相關集合對該操作沒有影響;進行下一次選擇操作才會看到此更改。

可在任意時間取消鍵和關閉通道。因此,在一個或多個選擇器的鍵集中出現某個鍵並不意味著該鍵是有效的,也不意味著其通道處於打開狀態。如果存在另一個執行緒取消某個鍵或關閉某個通道的可能性,那麼應用程序程式碼進行同步時應該小心,並且必要時應該檢查這些條件。

阻塞在 select()select(long) 方法之一中的某個執行緒可能被其他執行緒以下列三種方式之一中斷:

close 方法在選擇器上是同步的,並且所有三個鍵集都與選擇操作中的順序相同。

一般情況下,選擇器的鍵和已選擇鍵集由多個共時執行緒使用是不安全的。如果這樣的執行緒可以直接修改這些鍵集之一,那麼應該通過對該鍵集本身進行同步來控制存取。這些鍵集的 iterator 方法所返回的迭代器是快速失敗 的:如果在創建迭代器後以任何方式(調用迭代器自身的 remove 方法除外)修改鍵集,則會拋出 ConcurrentModificationException

從以下版本開始:
1.4
另請參見:
SelectableChannel, SelectionKey

建構子摘要
protected Selector()
          初始化此類別的一個新實例。
 
方法摘要
abstract  void close()
          關閉此選擇器。
abstract  boolean isOpen()
          告知此選擇器是否已打開。
abstract  Set<SelectionKey> keys()
          返回此選擇器的鍵集。
static Selector open()
          打開一個選擇器。
abstract  SelectorProvider provider()
          返回創建此通道的提供者。
abstract  int select()
          選擇一組鍵,其相應的通道已為 I/O 操作準備就緒。
abstract  int select(long timeout)
          選擇一組鍵,其相應的通道已為 I/O 操作準備就緒。
abstract  Set<SelectionKey> selectedKeys()
          返回此選擇器的已選擇鍵集。
abstract  int selectNow()
          選擇一組鍵,其相應的通道已為 I/O 操作準備就緒。
abstract  Selector wakeup()
          使尚未返回的第一個選擇操作立即返回。
 
從類別 java.lang.Object 繼承的方法
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

建構子詳細資訊

Selector

protected Selector()
初始化此類別的一個新實例。

方法詳細資訊

open

public static Selector open()
                     throws IOException
打開一個選擇器。

通過調用系統級預設 SelectorProvider 物件的 openSelector 方法來創建新的選擇器。

返回:
新的選擇器
拋出:
IOException - 如果發生 I/O 錯誤

isOpen

public abstract boolean isOpen()
告知此選擇器是否已打開。

返回:
當且僅當此選擇器已打開時才返回 true

provider

public abstract SelectorProvider provider()
返回創建此通道的提供者。

返回:
創建此通道的提供者

keys

public abstract Set<SelectionKey> keys()
返回此選擇器的鍵集。

不可直接修改鍵集。僅在已取消某個鍵並且已註銷其通道後才移除該鍵。試圖修改鍵集會導致拋出 UnsupportedOperationException

鍵集是非執行緒安全的

返回:
此選擇器的鍵集
拋出:
ClosedSelectorException - 如果此選擇器已關閉

selectedKeys

public abstract Set<SelectionKey> selectedKeys()
返回此選擇器的已選擇鍵集。

可從已選擇鍵集中移除鍵,但是無法直接添加鍵。試圖向該鍵集中添加物件會導致拋出 UnsupportedOperationException

已選擇鍵集是非執行緒安全的

返回:
此選擇器的已選擇鍵集
拋出:
ClosedSelectorException - 如果此選擇器已關閉

selectNow

public abstract int selectNow()
                       throws IOException
選擇一組鍵,其相應的通道已為 I/O 操作準備就緒。

此方法執行非阻塞的選擇操作。如果自從前一次選擇操作後,沒有通道變成可選擇的,則此方法直接返回零。

調用此方法會清除所有以前調用 wakeup 方法所得的結果。

返回:
由選擇操作更新其準備就緒操作集的鍵的數目,該數目可能為零
拋出:
IOException - 如果發生 I/O 錯誤
ClosedSelectorException - 如果此選擇器已關閉

select

public abstract int select(long timeout)
                    throws IOException
選擇一組鍵,其相應的通道已為 I/O 操作準備就緒。

此方法執行處於阻塞網要的選擇操作。僅在至少選擇一個通道、調用此選擇器的 wakeup 方法、當前的執行緒已中斷,或者給定的逾時期滿(以先到者為準)後此方法才返回。

此方法不提供實時保證:它安排了逾時時間,就像調用 Object.wait(long) 方法一樣。

參數:
timeout - 如果為正,則在等待某個通道準備就緒時最多阻塞 timeout 毫秒;如果為零,則無限期地阻塞;必須為非負數
返回:
已更新其準備就緒操作集的鍵的數目,該數目可能為零
拋出:
IOException - 如果發生 I/O 錯誤
ClosedSelectorException - 如果此選擇器已關閉
IllegalArgumentException - 如果 timeout 參數的值為負

select

public abstract int select()
                    throws IOException
選擇一組鍵,其相應的通道已為 I/O 操作準備就緒。

此方法執行處於阻塞網要的選擇操作。僅在至少選擇一個通道、調用此選擇器的 wakeup 方法,或者當前的執行緒已中斷(以先到者為準)後此方法才返回。

返回:
已更新其準備就緒操作集的鍵的數目,該數目可能為零
拋出:
IOException - 如果發生 I/O 錯誤
ClosedSelectorException - 如果此選擇器已關閉

wakeup

public abstract Selector wakeup()
使尚未返回的第一個選擇操作立即返回。

如果另一個執行緒目前正阻塞在 select()select(long) 方法的調用中,則該調用將立即返回。如果當前未進行選擇操作,那麼在沒有同時調用 selectNow() 方法的情況下,對上述方法的下一次調用將立即返回。在任一情況下,該調用返回的值可能是非零的。如果未同時再次調用此方法,則照常阻塞 select()select(long) 方法的後續調用。

在兩個連續的選擇操作之間多次調用此方法與只調用一次的效果相同。

返回:
此選擇器

close

public abstract void close()
                    throws IOException
關閉此選擇器。

如果某個執行緒目前正阻塞在此選擇器的某個選擇方法中,則中斷該執行緒,如同調用該選擇器的 wakeup 方法那樣。

所有仍與此選擇器關聯的未取消鍵已無效、其通道已註銷,並且與此選擇器關聯的所有其他資源已釋放。

如果此選擇器已經關閉,則調用此方法無效。

關閉選擇器後,除了調用此方法或 wakeup 方法外,以任何其他方式繼續使用它都將導致拋出 ClosedSelectorException

拋出:
IOException - 如果發生 I/O 錯誤

JavaTM 2 Platform
Standard Ed. 6

提交錯誤或意見

版權所有 2008 Sun Microsystems, Inc. 保留所有權利。請遵守GNU General Public License, version 2 only