NIO中幾個非常重要的技術點

2021-06-02 01:17:09 字數 1882 閱讀 2244

這些都是在實踐中踩過雷的,今天某應用再次踩雷,把遇到的幾個雷都收集一下,給後來者參考。

1.即使是accept事件,沒有真正的read和write,channel也要關閉,否則unix domain socket會被洩漏(windows更可怕),因為nio的每個

channel上都有兩個fd用來監聽事件(接收和傳送走不同的fd)。

2.cancel事件導致cpu占用100%,

其原因就是呼叫key.cancel()時底層在下一次seelect前並沒有真正的取消。導致等待select事件返回卻又沒有返回我們註冊的key.這個事件不斷地

迴圈觸發,cpu一直處理返回 key為0的select()呼叫。解決方法有兩種,一是在key.cancel()後立即selectnow();但是如果是多執行緒併發操作,有

可能這兩行語句中間執行緒被切換,使得key.cancel()後沒有立即執行 selectnow().這在多selector情況下是可能的。另一種就是jetty處理方式,如果

select()返回0且連續幾次出現這樣的情況(有事件觸發返回,卻不是返回我們註冊的key),就將有效的key重新註冊到乙個新的selector上。其實

glassfish在處理多次次次次write返回為0的情況時也是這種策略。

示例**:(真實的專案中)

int selecttimeout = connectionconfig.getselecttimeout();

int allprocessmaxtime = connectionconfig.getallprocessmaxtime();

//selector在實現時有bug,epool底層可能會傳送乙個錯誤的訊號導致select方法提前返回,但沒有

//返回註冊的事件,而且不斷迴圈造成cpu100%

int slelectzerocount = 0;

int maxzerocount = 20;

int fixed = 0;

while (selector.isopen() && selector.keys().size() != 0 && allprocessmaxtime > 0) else

if (slelectzerocount > maxzerocount && fixed == 0)

}fixed = 1;

} else if (slelectzerocount > maxzerocount && fixed == 1)

//對channel進行正常處理

重新註冊的**:

private synchronized void changeselector(selector oldselector, selector newselector) 

object att = key.attachment();

try else

} catch (closedchannelexception e)

}try catch (ioexception e)

}

同樣對於網路狀態不好時,連續寫操作返回0的處理:

private void flushdata(selector selector, socketchannel socketchannel, bytebuffer bytebuffer)

throws ioexception

// 如果不對len==0(即當前網路不可用)的情況處理,則while(bytebuffer.hasremaining())可能一直

// 迴圈下去而消耗大量的cpu.

if (len == 0) else

if (count > maxcount)

}}

NIO中幾個非常重要的技術點

這些都是在實踐中踩過雷的,今天某應用再次踩雷,把遇到的幾個雷都收集一下,給後來者參考。1.即使是accept事件,沒有真正的read和write,channel也要關閉,否則unix domain socket會被洩漏 windows更可怕 因為nio的每個 channel上都有兩個fd用來監聽事件...

NIO中幾個非常重要的技術點

這些都是在實踐中踩過雷的,今天某應用再次踩雷,把遇到的幾個雷都收集一下,給後來者參考。1.即使是accept事件,沒有真正的read和write,channel也要關閉,否則unix domain socket會被洩漏 windows更可怕 因為nio的每個 channel上都有兩個fd用來監聽事件...

Java非常重要的幾個類

jdk7提供了7個阻塞佇列。分別是 阻塞佇列 blockingqueue 是乙個支援兩個附加操作的佇列。這兩個附加的操作是 在隊列為空時,獲取元素的執行緒會等待佇列變為非空。當佇列滿時,儲存元素的執行緒會等待佇列可用。阻塞佇列常用於生產者和消費者的場景,生產者是往佇列裡新增元素的執行緒,消費者是從佇...