Selector API用法
java.nio.channels
類 Selector
java.lang.Object java.nio.channels.Selector
- 直接已知子類:
- AbstractSelector
public abstract class Selectorextends Object
SelectableChannel 物件的多路複用器。
可通過呼叫此類的 open 方法建立選擇器,該方法將使用系統的預設選擇器提供者建立新的選擇器。也可通過呼叫自定義選擇器提供者的 openSelector 方法來建立選擇器。通過選擇器的 close 方法關閉選擇器之前,它一直保持開啟狀態。
鍵集
已選擇鍵集 是這樣一種鍵的集合,即在前一次選擇操作期間,檢測每個鍵的通道是否已經至少為該鍵的相關操作集所標識的一個操作準備就緒。此集合由 selectedKeys 方法返回。已選擇鍵集始終是鍵集的一個子集。
已取消鍵集 是已被取消但其通道尚未登出的鍵的集合。不可直接訪問此集合。已取消鍵集始終是鍵集的一個子集。
在新建立的選擇器中,這三個集合都是空集合。
通過某個通道的 register 方法註冊該通道時,所帶來的副作用是向選擇器的鍵集中添加了一個鍵。在選擇操作期間從鍵集中移除已取消的鍵。鍵集本身是不可直接修改的。
不管是通過關閉某個鍵的通道還是呼叫該鍵的 cancel 方法來取消鍵,該鍵都被新增到其選擇器的已取消鍵集中。取消某個鍵會導致在下一次選擇操作期間登出該鍵的通道,而在登出時將從所有選擇器的鍵集中移除該鍵。
通過選擇操作將鍵新增到已選擇鍵集中。可通過呼叫已選擇鍵集的 remove 方法,或者通過呼叫從該鍵集獲得的 iterator 的 remove 方法直接移除某個鍵。通過任何其他方式從不會將鍵從已選擇鍵集中移除;特別是,它們不會因為影響選擇操作而被移除。不能將鍵直接新增到已選擇鍵集中。
選擇
在每次選擇操作期間,都可以將鍵新增到選擇器的已選擇鍵集以及從中將其移除,並且可以從其鍵集和已取消鍵集中將其移除。選擇是由 select()、select(long) 和 selectNow() 方法執行的,執行涉及三個步驟:
-
將已取消鍵集中的每個鍵從所有鍵集中移除(如果該鍵是鍵集的成員),並登出其通道。此步驟使已取消鍵整合為空集。
-
在開始進行選擇操作時,應查詢基礎作業系統來更新每個剩餘通道的準備就緒資訊,以執行由其鍵的相關集合所標識的任意操作。對於已為至少一個這樣的操作準備就緒的通道,執行以下兩種操作之一:
-
如果該通道的鍵尚未在已選擇鍵集中,則將其新增到該集合中,並修改其準備就緒操作集,以準確地標識那些通道現在已報告為之準備就緒的操作。丟棄準備就緒操作集中以前記錄的所有準備就緒資訊。
-
如果該通道的鍵已經在已選擇鍵集中,則修改其準備就緒操作集,以準確地標識所有通道已報告為之準備就緒的新操作。保留準備就緒操作集以前記錄的所有準備就緒資訊;換句話說,基礎系統所返回的準備就緒操作集是和該鍵的當前準備就緒操作集按位分開 (bitwise-disjoined) 的。
-
-
如果在步驟 (2) 的執行過程中要將任意鍵新增到已取消鍵集中,則處理過程如步驟 (1)。
是否阻塞選擇操作以等待一個或多個通道準備就緒,如果這樣做的話,要等待多久,這是三種選擇方法之間的唯一本質差別。
併發性
選擇器自身可由多個併發執行緒安全使用,但是其鍵集並非如此。
選擇操作在選擇器本身上、在鍵集上和在已選擇鍵集上是同步的,順序也與此順序相同。在執行上面的步驟 (1) 和 (3) 時,它們在已取消鍵集上也是同步的。
在執行選擇操作的過程中,更改選擇器鍵的相關集合對該操作沒有影響;進行下一次選擇操作才會看到此更改。
可在任意時間取消鍵和關閉通道。因此,在一個或多個選擇器的鍵集中出現某個鍵並不意味著該鍵是有效的,也不意味著其通道處於開啟狀態。如果存在另一個執行緒取消某個鍵或關閉某個通道的可能性,那麼應用程式程式碼進行同步時應該小心,並且必要時應該檢查這些條件。
阻塞在 select() 或 select(long) 方法之一中的某個執行緒可能被其他執行緒以下列三種方式之一中斷:
-
通過呼叫選擇器的 wakeup 方法,
-
通過呼叫選擇器的 close 方法,或者
-
在通過呼叫已阻塞執行緒的 interrupt 方法的情況下,將設定其中斷狀態並且將呼叫該選擇器的 wakeup 方法。
- 從以下版本開始:
- 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 錯誤