這些都是在實踐中踩過雷的,今天某應用再次踩雷,把遇到的幾個雷都收集一下,給後來者參考。
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 是乙個支援兩個附加操作的佇列。這兩個附加的操作是 在隊列為空時,獲取元素的執行緒會等待佇列變為非空。當佇列滿時,儲存元素的執行緒會等待佇列可用。阻塞佇列常用於生產者和消費者的場景,生產者是往佇列裡新增元素的執行緒,消費者是從佇...