nio是什么?Non-blocking IO(非阻塞式io),是jdk 1.4之后推出的新的通訊技術(shù)方案,它與傳統(tǒng)的socket阻塞式io不同,通過這種技術(shù)方案能夠優(yōu)化服務(wù)器資源,這種優(yōu)化方式是通過復(fù)雜的技術(shù)方法來減少線程的上下文切換得來的。是不是看不懂?看不懂沒關(guān)系,這不重要;
如果看到這里的親們是對(duì)nio感興趣的,能夠靜得下心來,把手機(jī)放在一邊,雖然這樣的代價(jià)挺大的,你可能會(huì)被在乎你的人瘋狂罵,被罵不要怪我啊,但是,可以肯定的是,nio對(duì)你來說再也不是難點(diǎn),那么請(qǐng)大家移步這里 http://ifeve.com/java-nio-all/ ,這里的文章說的對(duì)新手來講,簡(jiǎn)直不要太友好,作者是Jakob? Jenkov。靜下心來看完,絕對(duì)有收獲。畢竟這里,只是我的總結(jié)。
我們?yōu)槭裁从X得nio難?很簡(jiǎn)單,因?yàn)樵趯W(xué)校里面幾乎沒有應(yīng)用的場(chǎng)景,在學(xué)校里面使用io通訊都用不上,更何況是并發(fā)量大應(yīng)用場(chǎng)景的nio了。
so,第一個(gè)問題,我們?yōu)槭裁匆胣io?
當(dāng)然是傳統(tǒng)的io滿足不了我們的產(chǎn)品需求啦;ok,如果面試的時(shí)候這么回答,可能面試官會(huì)面帶微笑對(duì)你吧,反正很危險(xiǎn)。至于答案,其實(shí)我也不知道,因?yàn)槲乙矝]有被面過,哈哈哈,按照我的理解,那是因?yàn)閭鹘y(tǒng)的io在申明一個(gè)BufferedReader之后,調(diào)用readLine()方法去讀取數(shù)據(jù),如果數(shù)據(jù)沒有準(zhǔn)備好的話,這個(gè)線程會(huì)一直阻塞在這里,那么當(dāng)這樣的線程數(shù)量非常多的時(shí)候,第一會(huì)造成資源的極大浪費(fèi),因?yàn)檫@個(gè)時(shí)候線程不會(huì)干別的事情,第二,數(shù)據(jù)準(zhǔn)備好之后,會(huì)從阻塞狀態(tài)切換到就緒太,大量的線程頻繁的切換,所帶來的服務(wù)器系統(tǒng)資源消耗很大。所以就提出了nio,當(dāng)然還有別的原因啦,個(gè)人看法不同罷了,但是隨著之后計(jì)算機(jī)硬件的飛速發(fā)展,好像這些在以后也不是啥問題呀,壕的世界看法可能不太一樣。當(dāng)然,這里并不是說io不好,其實(shí)只是在不同的場(chǎng)景下應(yīng)用不同的技術(shù)罷了,比如io就很適合用在并發(fā)量不大,但是需要傳送大量帶寬數(shù)據(jù)的場(chǎng)景,因?yàn)檫@個(gè)不需要去維護(hù)流或者buffer。
那么nio究竟怎么用呢?
nio中有非常多的組件,但是最為核心的是三個(gè),selector,channel,和buffer,他們?nèi)咧g的關(guān)系是什么樣的呢?圖一可以粗略的表示一下,emmmm,畫的有點(diǎn)丑。

那么這三者里面的使用是怎么聯(lián)系的呢?首先,channel按照相應(yīng)的事件向selector注冊(cè),比如連接事件SelectionKey.OP_CONNECT或者讀就緒事件SelectionKey.OP_READ,當(dāng)然還有寫,和就緒事件,注冊(cè)之后,會(huì)返回一個(gè)SelectionKey 對(duì)象,這個(gè)對(duì)象中,你可以得到相應(yīng)的channel,selector,響應(yīng)過的事件等等信息,當(dāng)有相應(yīng)的事件發(fā)生時(shí),向selector注冊(cè)過的channel就會(huì)收到消息,而在nio通信模式中,channel始終是和buffer之間進(jìn)行數(shù)據(jù)交換的,所以在有的文章里面也說,nio是面向buffer的,而io是面向流的。
channel進(jìn)行數(shù)據(jù)的讀寫使用的是兩個(gè)api,channel.read()從channel中將數(shù)據(jù)讀到buffer和channel.write()從buffer中拿取數(shù)據(jù)寫入到channel中,而buffer中又設(shè)計(jì)到了3個(gè)主要概念,分別是capacity,position,和limit;capacity是指整個(gè)緩沖區(qū)的大小,而position和limit要根據(jù)讀模式或者寫模式的不同,同時(shí)有不同的含義。在寫模式下,position表示數(shù)據(jù)在換從區(qū)寫到的位置,而limit和capacity的值相同,但是調(diào)用flip()函數(shù)將寫模式切換到讀模式的時(shí)候,position表示0,而limit則處于寫模式時(shí)候的position位置,表示最多只能讀到這么多數(shù)據(jù)。
那么selector是怎么將通知信息及時(shí)的給channel的呢?底層涉及到了設(shè)計(jì)模式反應(yīng)器模式,基本的流程就是在線程中循環(huán)去訪問selector的select()方法,看是否大于0,因?yàn)榇笥?返回的就是有就緒的事件了,這個(gè)時(shí)候,調(diào)用seletor的selectedKeys()方法,會(huì)返回selectedKey的set集合,將集合變成iterator對(duì)象,對(duì)每個(gè)selectedKey對(duì)象訪問,看是否是什么事件,然后執(zhí)行相應(yīng)的處理,處理完之后,記得將對(duì)象移除,如果不移除,那么這個(gè)selectedKey對(duì)象會(huì)保留到下一次。
看到這里的小伙伴,勇氣可嘉,之前有迷惑的,我相信你是有收獲的,之前完全沒有接觸的,我相信你也是有收獲的,因?yàn)槭叩脑挘催@個(gè)肯定特別容易睡的著,催眠效果絕對(duì)好,之前懂nio的,你可能怪我沒貼代碼咯,至于底層的反應(yīng)器模式,接下來會(huì)持續(xù)更新。