NIO選擇器
1 選擇器基礎
您需要將之前建立的一個或多個可選擇的通道註冊到選擇器物件中。
一個表示通道和選擇器的鍵將會被返回。
選擇鍵會記住您關心的通道。
它們也會追蹤對應的通道是否已經就緒。
當您呼叫一個選擇器物件的 select()方法時,相關的鍵值會被更新,用來檢查所有被註冊到該選擇器的通道。
您可以獲取一個鍵的集合,從而找到當時已經就緒的通道。
通過遍歷這些鍵,您可以選擇出每個從上次您呼叫 select( )開始直到現在,已經就緒的通道。
從最基礎的層面來看,選擇器提供了詢問通道是否已經準備好執行每個 I/0 操作的能力。
呼叫者可以輕鬆地決定多個通道中的哪一個準備好要執行。
有兩種方式可以選擇:
被激發的執行緒可以處於休眠狀態,直到一個或者多個註冊到選擇器的通道就緒,
或者它也可以週期性地輪詢選擇器,看看從上次檢查之後,是否有通道處於就緒狀態。
1.1 選擇器、可選擇通道和選擇鍵類
選擇器(Selector)
選擇器類管理著一個被註冊的通道集合的資訊和它們的就緒狀態。通道是和選擇器一起被註冊的,並且使用選擇器來更新通道的就緒狀態。當這麼做的時候,可以選擇將被激發的執行緒掛起,直到有就緒的的通道。
可選擇通道(SelectableChannel)
這個抽象類提供了實現通道的可選擇性所需要的公共方法。它是所有支援就緒檢查的通道類的父類。FileChannel 物件不是可選擇的,因為它們沒有繼承 SelectableChannel(見圖 4-2)。所有 socket 通道都是可選擇的,包括從管道(Pipe)物件的中獲得的通道。SelectableChannel 可以被註冊到 Selector 物件上,同時可以指定對那個選擇器而言,那種操作是感興趣的。一個通道可以被註冊到多個選擇器上,但對每個選擇器而言只能被註冊一次。
選擇鍵(SelectionKey)
選 擇 鍵 封 裝 了 特 定 的 通 道 與 特 定 的 選 擇 器 的 注 冊 關 系 。 選 擇 鍵 對 象 被SelectableChannel.register( ) 返回並提供一個表示這種註冊關係的標記。選擇鍵包含了兩個位元集(以整數的形式進行編碼),指示了該註冊關係所關心的通道操作,以及通道已經準備好的操作。
SelectableChannel(可選擇通道)
public abstract SelectionKey register (Selector sel, int ops)
將通道註冊到一個選擇器上,如果註冊阻塞的通道。會拋異常。
通道一旦被註冊,就不能回到阻塞狀態。試圖這麼做,也會拋異常的。
public abstract SelectionKey register (Selector sel, int ops,Object att)
返回一個封裝了兩個物件的關係的選擇鍵物件。最後的att就是附加的附件
public abstract boolean isRegistered( );
可以呼叫 isRegistered( )方法來檢查一個通道是否被註冊到任何一個選擇器上。
這個方法沒有提供關於通道被註冊到哪個選擇器上的資訊,而只能知道它至少被註冊到了一個選擇器上。
在一個鍵被取消之後,直到通道被登出為止,可能有時間上的延遲。這個方法只是一個提示,而不是確切的答案。
public abstract SelectionKey keyFor (Selector sel);
返回與該通道和指定的選擇器相關的鍵
public abstract int validOps( );
獲取特定的通道所支援的操作集合
public abstract void configureBlocking (boolean block)
public abstract boolean isBlocking( );
public abstract Object blockingLock( );
通道在被註冊到一個選擇器上之前,必須先設定為非阻塞模式(通過呼叫 configureBlocking(false))。
一個給定的通道可以被註冊到多於一個 的選 擇器上 ,而 且不 需要 知道它 被注 冊了 那個 Selector 物件上 。
1.2 建立選擇器
Selector selector = Selector.open( );
channel1.register (selector, SelectionKey.OP_READ);
選擇器才是提供管理功能的物件,而不是可選擇通道物件。選擇器物件對註冊到它之上的通道執行就緒選擇,並管理選擇鍵。
channel2.register (selector, SelectionKey.OP_WRITE);
channel3.register (selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE);
readyCount = selector.select (10000); //等待十秒後查詢已經準備好的通道
- SelectionKey.OP_ACCEPT —— 接收連線繼續事件,表示伺服器監聽到了客戶連線,伺服器可以接收這個連線了
- SelectionKey.OP_CONNECT —— 連線就緒事件,表示客戶與伺服器的連線已經建立成功
- SelectionKey.OP_READ —— 讀就緒事件,表示通道中已經有了可讀的資料,可以執行讀操作了(通道目前有資料,可以進行讀操作了)
- SelectionKey.OP_WRITE —— 寫就緒事件,表示已經可以向通道寫資料了(通道目前可以用於寫操作)
這裡 注意,下面兩種,SelectionKey.OP_READ ,SelectionKey.OP_WRITE ,
- 1.當向通道中註冊SelectionKey.OP_READ事件後,如果客戶端有向快取中write資料,下次輪詢時,則會 isReadable()=true;
- 2.當向通道中註冊SelectionKey.OP_WRITE事件後,這時你會發現當前輪詢執行緒中isWritable()一直為ture,如果不設定為其他事件
2 選擇鍵
SelectionKey(選擇鍵)
public static final int OP_READ
public static final int OP_WRITE
public static final int OP_CONNECT
public static final int OP_ACCEPT
public abstract SelectableChannel channel( );//返回與該鍵相關的SelectableChannel 物件
public abstract Selector selector( );//返回相關的 Selector 物件
public abstract void cancel( );//終結鍵物件和通道的關係,不會立即取消,只是會放在選擇器的已取消的集合裡,註冊不會立即被取消,但鍵會立即失效。當再次呼叫選擇器的select()時,已取消的鍵的集合中的被取消的鍵就會被清理掉。並且相應的登出也將完成。通道會被登出,而新的SelectionKey將被返回。
public abstract boolean isValid( );//檢查選擇鍵是否仍然有效。
public abstract int interestOps( );//獲取當前的 interest 集合
public abstract void interestOps (int ops);
public abstract int readyOps( );//獲取相關的通道的已經就緒的操作
public final boolean isReadable( )
public final boolean isWritable( )
public final boolean isConnectable( )
public final boolean isAcceptable( )
public final Object attach (Object ob)//將在鍵物件中儲存所提供的物件的引用。SelectionKey 類除了儲存它之外,不會將它用於任何其他用途。任何一個之前儲存在鍵中的附件引用都會被替換
public final Object attachment( )//呼叫 attachment( )方法來獲取與鍵關聯的附件控制代碼。如果沒有附件,或者顯式地通過 null 方法進行過設定,這個方法將返回 null。
SelectionKey key = channel.register (selector, SelectionKey.OP_READ, myObject);
等價於:
SelectionKey key = channel.register (selector, SelectionKey.OP_READ);
key.attach (myObject);
一個鍵表示了一個特定的通道物件和一個特定的選擇器物件之間的註冊關係 。
當通道關閉時,所有相關的鍵會自動取消
當選擇器關閉時,所有被註冊到該選擇器的通道都將被登出,並且相關的鍵將立即被無效化(取消)。一旦鍵被無效化,呼叫它的與選擇相關的方法就將丟擲 CancelledKeyException。
一個 SelectionKey 物件包含兩個以整數形式進行編碼的位元掩碼:一個用於指示那些通道/選擇器組合體所關心的操作(instrest 集合),另一個表示通道準備好要執行的操作(ready 集合)。 interest 集合可以通過呼叫鍵物件的 interestOps( )方法來獲取.
這個 interset 集合永遠不會被選擇器改變,但您可以通過呼叫 interestOps( )方法並傳入一個新的位元掩碼引數來改變它。
當相關的 Selector 上的 select( )操作正在進行時改變鍵的 interest 集合,不會影響那個正在進行的選擇操作。所有更改將會在 select( )的下一個呼叫中體現出來。
ready 集合是 interest集合的子集,並且表示了 interest 集合中從上次呼叫 select( )以來已經就緒的那些操作。
有四個通道操作可以被用於測試就緒狀態
isReadable( ),isWritable( ),isConnectable( ), 和 isAcceptable( )
選擇器中不能直接改變鍵的ready集合。
attach和attachment方法是允許您在鍵上放置一個“附件”,並在後面獲取它。
如果選擇鍵的存續時間很長,但您附加的物件不應該存在那麼長時間,請記得在完成後清理附件。否則,您附加的物件將不能被垃圾回收,您將會面臨記憶體洩漏問題。
總體上說,SelectionKey 物件是執行緒安全的,但知道修改 interest 集合的操作是通過 Selector 物件進行同步的是很重要的。這可能會導致 interestOps( )方法的呼叫會阻塞不確定長的一段時間。
3 選擇器
Selector(選擇器)
public static Selector open( ) throws IOException
例項化
public abstract boolean isOpen( );
測試一個選擇器是否處於被開啟狀態被開啟狀態
public abstract void close( ) throws IOException;
是使用的時候呼叫這個,釋放記憶體,並將相關的選擇鍵設定為無效。
public abstract SelectionProvider provider( );
決定由哪個 SelectorProvider 物件來建立給定的 Selector 例項
public abstract int select( ) throws IOException;
public abstract int select (long timeout) throws IOException;
public abstract int selectNow( ) throws IOException;
public abstract void wakeup( );
public abstract Set keys( );
public abstract Set selectedKeys( );
選擇器維護了一個需要監控的通道的集合。
3.1 選擇過程
Selector
public abstract Set keys( );
返回已註冊的鍵的集合
public abstract Set selectedKeys( );
返回通道已經就緒的鍵的集合
public abstract int select( ) throws IOException;
無線阻塞,直到有通道就緒了
public abstract int select (long timeout) throws IOException;
設定超時時間,讓該執行緒不要一直阻塞
public abstract int selectNow( ) throws IOException;
不等待若沒有就緒的通道直接返回0
public abstract void wakeup( );
已註冊的鍵的集合(Registered key set)
通過keys()方法返回已註冊的鍵的集合,註冊是並不一定都仍有效,這個集合是不可以直接修改的,試圖這麼做會報 java.lang.UnsupportedOperationException
已選擇的鍵的集合(Selected key set)
已註冊的鍵的集合的子集。這個集合的每個成員的相關通道都是被選擇器判斷為已經選擇好的。並且包含interest集合中的操作。通過selectedKeys()方法返回。
已選擇的鍵的集合和redy集合是不一樣的,已選擇的鍵的集合是選擇器中的集合,這些集合中的鍵所關聯的通道已經準備好的操作就存在ready集合中,且ready內嵌在鍵中。
鍵可以直接從這個集合中移除,但是不能新增。
已取消的鍵的集合(Cancelled key set)
已註冊的鍵的集合的子集,這個子集包含了cancel()方法被呼叫過的鍵(這個鍵已經被無效化),但他們還沒有被登出。
這個集合是選擇器物件的私有成員,不能直接訪問。
在一個剛初始化的Selector物件中,這三個集合都是空的。
Selector 類的核心是選擇過程
選擇操作是當三種形式的 select( )中的任意一種被呼叫時,由選擇器執行的。不管是哪一種形式的呼叫,下面步驟將被執行:
1.已取消的鍵的集合將會被檢查。如果它是非空的,每個已取消的鍵的集合中的鍵將從另外兩個集合中移除,並且相關的通道將被登出。這個步驟結束後,已取消的鍵的集合將是空的。
2.已註冊的鍵的集合中的鍵的 interest 集合將被檢查。在這個步驟中的檢查執行過後,對interest 集合的改動不會影響剩餘的檢查過程。
呼叫select方法時,如果沒有通道已經準備好,執行緒可能會在這時阻塞,通常會有一個超時值。
對於那些還沒準備好的通道將不會執行任何的操作。
對於那些作業系統指示至少已經準備好 interest 集合中的一種操作的通道,將執行以下兩種操作中的一種:
a.如果通道的鍵還沒有處於已選擇的鍵的集合中,那麼鍵的 ready 集合將被清空,然後表示作業系統發現的當前通道已經準備好的操作的位元掩碼將被設定。
b.否則,也就是鍵在已選擇的鍵的集合中。鍵的 ready 集合將被表示作業系統發現的當前已經準備好的操作的位元掩碼更新。所有之前的已經不再是就緒狀態的操作不會被清除。事實上,所有的位元位都不會被清理。由作業系統決定的 ready 集合是與之前的 ready 集合按位分離的,一旦鍵被放置於選擇器的已選擇的鍵的集合中,它的 ready 集合將是累積的。位元位只會被設定,不會被清理。
3.步驟 2 可能會花費很長時間,特別是所激發的執行緒處於休眠狀態時。與該選擇器相關的鍵可能會同時被取消。當步驟 2 結束時,步驟 1 將重新執行,以完成任意一個在選擇進行的過程中,鍵已經被取消的通道的登出。
4.select 操作返回的值是 ready 集合在步驟 2 中被修改的鍵的數量,而不是已選擇的鍵的集合中的通道的總數。
使用內部的已取消的鍵的集合來延遲登出,是一種防止執行緒在取消鍵時阻塞,並防止與正在進行的選擇操作衝突的優化。
select選擇流程圖
Selector 類的 select( )方法有以下三種不同的形式:
selectNow()方法執行就緒檢查過程,但不阻塞。如果當前沒有通道就緒,它將立即返回 0。
public abstract int select( ) throws IOException;
無線阻塞,直到有通道就緒了
public abstract int select (long timeout) throws IOException;
設定超時時間,讓該執行緒不要一直阻塞
3.2 停止選擇過程
Selector
public abstract void wakeup( );
wakeup( ),提供了使執行緒從被阻塞的 select( )方法中優雅地退出的能力。
有三種方式可以喚醒在 select( )方法中睡眠的執行緒:
呼叫 wakeup( )
呼叫wakeup()方法會讓選擇器上的第一個還沒有返回的選擇操作立即返回。如果當前沒有進行中的選擇,那麼下一次呼叫的select()方法會立即返回。後續的選擇操縱會正常進行。
在選擇操作期間多次呼叫wakeup()方法與呼叫它一次沒有什麼不同。
有時候,我們不需要這種延遲喚醒,那麼在呼叫wakeup()後,再呼叫selectNow()方法來繞過這個問題。
呼叫 close( )
呼叫一個close()方法,任何一個在選擇操作中阻塞的select()方法都會被喚醒,與選擇器相關的通道會被登出,鍵也會被取消。
呼叫 interrupt( )
睡眠中的執行緒的interrupt()被呼叫,它的返回狀態將被設定。如果喚醒執行緒之後將檢視在通道上執行I/O操作,通道將立即關閉。
請注意這些方法中的任意一個都不會關閉任何一個相關的通道。中斷一個選擇器與中斷一個通道是不一樣的(參見 3.3 節)。選擇器不會改變任意一個相關的通道,它只會檢查它們的狀態。當一個在 select( )方法中睡眠的執行緒中斷時,對於通道的狀態而言,是不會產生歧義的。
3.3 管理選擇鍵
選擇是累積的。
一旦一個選擇器講一個鍵新增到已選擇的鍵的集合中,這個鍵就不會被移除
一旦一個鍵處於已選擇集合中,這個鍵的ready集合將只會被設定,而不會被清理。
合理地使用選擇器的祕訣是理解選擇器維護的選擇鍵集合所扮演的角色。
一旦通道上一個操作就緒時,相關聯的鍵的read集合就會被清空,然後把已經就緒的操作加進來。然後這個鍵就會被新增到已選擇的集合中。
清理一個 SelectKey 的 ready 集合的方式是將這個鍵從已選擇的鍵的集合中移除。因為只有存在已選擇集合中的鍵才被認為是合法的,這些鍵會長久存在,不會被清理,直到被移除。
close()方法與select()方法一樣。也有可能一直阻塞。
還在進行的選擇過程中,所有對close()的呼叫都會被阻塞,直到選擇過程結束,或者執行選擇的執行緒進入睡眠。
NIO完整例子:
public class NIOServer {
/*標識數字*/
private int flag = 0;
/*緩衝區大小*/
private int BLOCK = 4096;
/*接受資料緩衝區*/
private ByteBuffer sendbuffer = ByteBuffer.allocateDirect(BLOCK);
/*傳送資料緩衝區*/
private ByteBuffer receivebuffer = ByteBuffer.allocateDirect(BLOCK);
private Selector selector;
public NIOServer(int port) throws IOException {
// 開啟伺服器套接字通道
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
// 伺服器配置為非阻塞
serverSocketChannel.configureBlocking(false);
// 檢索與此通道關聯的伺服器套接字
ServerSocket serverSocket = serverSocketChannel.socket();
// 進行服務的繫結
serverSocket.bind(new InetSocketAddress(port));
// 通過open()方法找到Selector
selector = Selector.open();
// 註冊到selector,等待連線
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
System.out.println("Server Start----8888:");
}
// 監聽
private void listen() throws IOException {
while (true) {
// 選擇一組鍵,並且相應的通道已經開啟
selector.select();
// 返回此選擇器的已選擇鍵集。
Set<SelectionKey> selectionKeys = selector.selectedKeys();
Iterator<SelectionKey> iterator = selectionKeys.iterator();
while (iterator.hasNext()) {
SelectionKey selectionKey = iterator.next();
iterator.remove();
handleKey(selectionKey);
}
}
}
// 處理請求
private void handleKey(SelectionKey selectionKey) throws IOException {
// 接受請求
ServerSocketChannel server = null;
SocketChannel client = null;
String receiveText;
String sendText;
int count=0;
// 測試此鍵的通道是否已準備好接受新的套接字連線。
if (selectionKey.isAcceptable()) {
// 返回為之建立此鍵的通道。
server = (ServerSocketChannel) selectionKey.channel();
// 接受到此通道套接字的連線。
// 此方法返回的套接字通道(如果有)將處於阻塞模式。
client = server.accept();
// 配置為非阻塞
client.configureBlocking(false);
// 註冊到selector,等待連線
client.register(selector, SelectionKey.OP_READ);
} else if (selectionKey.isReadable()) {
// 返回為之建立此鍵的通道。
client = (SocketChannel) selectionKey.channel();
//將緩衝區清空以備下次讀取
receivebuffer.clear();
//讀取伺服器傳送來的資料到緩衝區中
count = client.read(receivebuffer);
if (count > 0) {
receiveText = new String( receivebuffer.array(),0,count);
System.out.println("伺服器端接受客戶端資料--:"+receiveText);
client.register(selector, SelectionKey.OP_WRITE);
}
} else if (selectionKey.isWritable()) {
//將緩衝區清空以備下次寫入
sendbuffer.clear();
// 返回為之建立此鍵的通道。
client = (SocketChannel) selectionKey.channel();
sendText="message from server--" + flag++;
//向緩衝區中輸入資料
sendbuffer.put(sendText.getBytes());
//將緩衝區各標誌復位,因為向裡面put了資料標誌被改變要想從中讀取資料發向伺服器,就要復位
sendbuffer.flip();
//輸出到通道
client.write(sendbuffer);
System.out.println("伺服器端向客戶端傳送資料--:"+sendText);
client.register(selector, SelectionKey.OP_READ);
}
}
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
int port = 8888;
NIOServer server = new NIOServer(port);
server.listen();
}
}
4 非同步關閉能力
任何時候都可能關閉一個通道或者取消一個選擇鍵。除非我們用同步,否則鍵和通道的狀態的變化都是意料之外的改變。
一個特定的鍵的集合中的一個鍵的存在不能保證鍵仍然是有效,或者通道仍然是開啟的
關閉通道的過程不應該是一個耗時的操作。
請不要自己維護鍵的集合!理解選擇的過程!
如果你試圖使用一個已經失效的鍵,大多數方法將丟擲CancelledKeyException。
5 選擇過程的擴充套件性
但只使用一個執行緒來服務所有可選擇的通道是否是一個好主意呢?這要看情況。
對單 CPU 的系統而言這可能是一個好主意,因為在任何情況下都只有一個執行緒能夠執行。
在一個有 n 個 CPU 的系統上,當一個單一的執行緒線性地輪流處理每一個執行緒時,可能有 n-1 個 cpu 處於空閒狀態。
在大量通道上執行就緒選擇並不會有很大的開銷,大多數工作是由底層作業系統完成的。
在第一個場景中,
如果您想要將更多的執行緒來為通道提供服務,一個更好的策略是對所有的可選擇通道使用一個選擇器,並將對就緒通道的服務委託給其他執行緒。您只用一個執行緒監控通道的就緒狀態並使用一個協調好的工作執行緒池來處理共接收到的資料。根據部署的條件,執行緒池的大小是可以調整的(或者它自己進行動態的調整)。對可選擇通道的管理仍然是簡單的,而簡單的就是好的。
第二個場景中,
某些通道要求比其他通道更高的響應速度,可以通過使用兩個選擇器來解決。
一個為命令連線服務,另一個為普通連線服務。
但這種場景也可以使用與第一個場景十分相似的辦法來解決。通道可以根據功能由不同的工作執行緒來處理。它們可能可以是日誌執行緒池,命令/控制執行緒池,狀態請求執行緒池,等等。
相關推薦
NIO 選擇器 Selector
字節 () 激發 就是 異常檢查 執行 1.4 移植 異常 選擇器提供選擇執行已經就緒的任務的能力,這使得多元 I/O 成為可能。就像在第一章中描述的那樣,就緒選擇和多元執行使得單線程能夠有效率地同時管理多個 I/O 通道(Channels)。C/C++代碼的工具箱中,
Java Nio選擇器Selector
Selector(選擇器)是Java NIO中能夠檢測一到多個NIO通道,並能夠知曉通道是否為諸如讀寫事件做好準備的元件。這樣,一個單獨的執行緒可以管理多個channel,從而管理多個網路連線 ,減少伺服器的效能開銷。 建立Selector 通過Selector 提供的
Java NIO 選擇器(Selector)的內部實現(poll epoll)
之前強調這麼多關於linux核心的poll及epoll,無非是想讓大家先有個認識: Java NIO中的選擇器依賴作業系統核心的這些系統呼叫,我們這裡只講解與linux核心相關的NIO實現,當然,windows或其他作業系統實現大體上是類似的,相信大家也可以觸類旁通。 那
NIO選擇器
1 選擇器基礎 您需要將之前建立的一個或多個可選擇的通道註冊到選擇器物件中。 一個表示通道和選擇器的鍵將會被返回。 選擇鍵會記住您關心的通道。 它們也會追蹤對應的通道是否已經就緒。 當您呼叫一個選擇器物件的 s
Java NIO 選擇器 Selector
選擇器 Selector 是 I/O 多路複用的核心元件,它可以監控實現了 SelectableChannel 的[通道](https://www.cnblogs.com/robothy/p/14234437.html)的就緒情況。有了多路複用(multiplexing) I/O 模型,使得單執行緒的 Jav
Java NIO之選擇器分析
目錄 簡介 選擇器Selector 選擇鍵SelectionKey 通過Selector選擇通道 案例 簡介 傳統的IO流請求都是一個請求需要一個執行緒來處理,如果請求數量比較龐大,那麼對於作業系統來說,執行緒佔用一定的記憶體,執行緒上下文切換開銷也
Java NIO之選擇器
1.簡介 前面的文章說了緩衝區,說了通道,本文就來說說 NIO 中另一個重要的實現,即選擇器 Selector。在更早的文章中,我簡述了幾種 IO 模型。如果大家看過之前的文章,並動手寫過程式碼的話。再看 Java 的選擇器大概就會知道它是什麼了,以及怎麼用了。選擇器是 Java 多路複用模型的
《Java NIO》學習筆記四 選擇器(Selector)
一、選擇器基礎 選擇器(Selector): 選擇器類管理著一個被註冊的通道集合的資訊和它們的就緒狀態。通道是和選擇器一起被註冊的,並且使用選擇器來更新通道的就緒狀態。 可選擇通道(SelectorChannel): 這個抽象類提供了實現通道的可選擇性所需要的公共方法。Se
【Java8原始碼分析】NIO包-Selector選擇器
1 概述 Java NIO 由以下幾個核心部分組成: Buffer Channel Selectors 相關類的使用方法可以參考Java NIO 系列教程,寫的通俗易懂。 本文主要從原始碼方面分析一下Selector選擇器。關
Java NIO使用及原理之--選擇器Seclector
在上一篇文章中介紹了關於緩衝區的一些細節內容,現在終於可以進入NIO中最有意思的部分非阻塞I/O。通常在進行同步I/O操作時,如果讀取資料,程式碼會阻塞直至有 可供讀取的資料。同樣,寫入呼叫將會阻塞直至資料能夠寫入。傳統的Server/Client模式會基於TPR(Thread per Request),伺
Java NIO通俗程式設計之選擇器Selector(四)
最後一步就是根據不同的事件,編寫相應的處理程式碼:/* * 根據不同的事件做處理 * */ protected void process(SelectionKey key) throws IOException{ // 接收請求 if (key.isAcceptable()) {
java nio學習:緩衝區、通道和選擇器
java nio中引入了緩衝區,緩衝區中的資料可以寫入通道,也可以從通道中讀取資料到緩衝區。nio中的緩衝區就是對陣列的簡單封裝,緩衝區有讀模式和寫模式,緩衝區的屬性有容量(capacity)、限制(limit)、位置(position),容量表示陣列的大小,限制表示第一個
NIO學習筆記--Selector選擇器基礎
Selector是Java NIO中檢測一個或多個Channel的,同時確定哪些channel是否已經可以進行讀或者寫的元件,這樣一個執行緒就可以管理多個channel,從而管理多個網路連線,1.Selector概述:Selector的優點:可以使用更少執行緒來管理chann
Java NIO系列4:通道和選擇器
前言 今天加班回來,終於有時間繼續更新NIO的文章了。在前一篇文章我們講解了緩衝區的知識,並通過程式碼演示瞭如何使用緩衝區的API完成一些操作。這裡要講的通道於緩衝區關係密切,簡單來說,緩衝區是填充資料的載體,而通道則可以理解為傳輸資料的載體。回憶在TCP/I
NIO中和選擇器Selector
NIO中和選擇器Selector 在上一篇的JAVA中NIO再深入我們學會了如何使用Buffer,而在Java中IO和NIO中我們
NIO(三):Selector選擇器
一.堵塞式與非堵塞式 在傳統IO中,將資料由當前執行緒從客戶端傳入服務端,由服務端的核心進行判斷傳過來的資料是否合法,核心中是否存在資料。 如果不存在資料 ,並且資料並不合法,當前執行緒將會堵塞等待。當前執行緒將無法進行下一步傳輸,進行排隊現象。降低系統性能。 為了解決這一步問題,呼叫資源開闢多
Java NIO:選擇器
最近打算把Java網路程式設計相關的知識深入一下(IO、NIO、Socket程式設計、Netty) Java NIO主要需要理解緩衝區、通道、選擇器三個核心概念,作為對Java I/O的補充, 以提升大批量資料傳輸的效率。 學習NIO之前最好能有基礎的網路程式設計知識 [Java I/O流](https
分針網——IT教育:jquery選擇器的用法
jQuery選擇器是jQuery庫的一大特色,用這些選擇器不但可以省去繁瑣的JavaScript 書寫方式,還可以節省時間和效率,正是有這些jQuery選擇器,才讓我們更容易的操作JavaScript的dom。 1. 基本選擇器 ·#id 根據
時間選擇器jquerry特效
清空 z-index format 獲取 sub tran cond hang button double-date.js代碼 $(function() { var dateStr = ‘<div class="date-list"><div cla
jQuery選擇器絕對定位實現div覆蓋
rip jquer 絕對定位 button min 覆蓋 str fun 選擇 新建html文件可以運行(jsp文件下不可運行) <!DOCTYPE html><html> <head> <meta charse