Java NIO--Selector

Selector簡介

Selector(選擇器)是javaNIO中能檢測一到多個(gè)NIO通道,并能夠知道通道是否為諸如讀寫事件做好準(zhǔn)備的組件。這樣的好處是,一個(gè)單獨(dú)的線程可以管理多個(gè)channel,從而可以管理多個(gè)網(wǎng)絡(luò)連接。

1.使用Selector的好處

對于操作系統(tǒng)而言,線程之間上下文切換的開銷很大,而且每個(gè)線程都要占用系統(tǒng)的一些資源。所以用單個(gè)線程來處理多個(gè)channels能提高性能。
但是現(xiàn)代操作系統(tǒng)和cpu在多任務(wù)方便表現(xiàn)的越來越好,所以多線程的開銷隨著時(shí)間的推移,變得越來越小了。所以可以使用多個(gè)Selector.

1.1Selector的創(chuàng)建

通過調(diào)用Selector.open()方法創(chuàng)建一個(gè)Selector

Selector selector = Selector.open();

1.2向Selector注冊通道

為了將Channel和Selector配合使用,必須將channel注冊到selector上,通過SelectableChannel.register()方法來實(shí)現(xiàn)。

channel.configureBlocking(false);
SelectionKey key = channel.register(selector,
Selectionkey.OP_READ);

register()方法的第二個(gè)參數(shù),這是一個(gè)“interest集合”,意思是在通過Selector監(jiān)聽Channel時(shí)對什么事情感興趣,有一下4中事件。

Connect
Accept
Read
Write

通道觸發(fā)了一個(gè)事件就是該事件已經(jīng)就緒。

SelectionKey.OP_CONNECT:某個(gè)channel成功連接到另一個(gè)服務(wù)器稱為“連接就緒”
SelectionKey.OP_ACCPET:一個(gè)server socket channel準(zhǔn)備好接收新進(jìn)入的連接稱為“接收就緒”
SelectionKey.OP_READ:一個(gè)有數(shù)據(jù)可讀的通道可以說是讀就緒。
SelectionKey.OP_WRITE.等待寫數(shù)據(jù)的通道可以說是寫就緒。

1.3SelectionKey

當(dāng)向Selector注冊Channel時(shí),register()方法會(huì)返回一個(gè)SelectionKey對象,這個(gè)對象包含了一些你感興趣的屬性。

interest集合:你所感興趣的事件集合
ready集合:通道已經(jīng)準(zhǔn)備就緒的集合
Channel:可以訪問channel Channel channel = selectionKey.channel();
Selector:可以訪問selector Selector selector = selectionKey.selector();

1.4Selector選擇通道

一旦向Selector注冊一個(gè)或者多個(gè)通道,可以調(diào)用幾個(gè)重載的select()方法,這些方法返回你所感興趣的事件(連接,接受,讀或?qū)懀┮呀?jīng)準(zhǔn)備就緒的哪些通道。

select():阻塞到至少有一個(gè)通道在你注冊上的事件就緒了。
select(long timeout):除了最長阻塞timeout毫秒
selectNow()不會(huì)阻塞:不管什么通道就緒都立刻返回。

1.5selectKeys()

一旦調(diào)用了select方法,并且返回值表明有一個(gè)或更多個(gè)通道就緒了,然后可以通過調(diào)用selector的selectedKeys()方法,訪問已選擇(selected key set)中的就緒通道。

Set selectedKeys = selector.selectedKeys();

可以遍歷這個(gè)已選擇的鍵集合來訪問就緒的通道。如下:

Set selectedKeys = selector.selectedKeys();
Iterator keyIterator = selectedKeys.iterator();
while(keyIterator.hasNext()) {
    SelectionKey key = keyIterator.next();
    if(key.isAcceptable()) {
        // a connection was accepted by a ServerSocketChannel.
    } else if (key.isConnectable()) {
        // a connection was established with a remote server.
    } else if (key.isReadable()) {
        // a channel is ready for reading
    } else if (key.isWritable()) {
        // a channel is ready for writing
    }
    keyIterator.remove();
}

這個(gè)循環(huán)遍歷選擇鍵集中的每個(gè)鍵,并檢測各個(gè)鍵所對應(yīng)的通道的就緒事件。

參考:http://ifeve.com/selectors/

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容