1.為什么要使用NIO
由于IO是基于阻塞IO模式的唯咬,讀寫操作都有可能會阻塞纱注。如果用單線程處理IO,就會導(dǎo)致在線程阻塞時胆胰,整個系統(tǒng)都掛掉了狞贱。一個解決方案就是使用多線程,一個IO連接對應(yīng)一個線程蜀涨,而多線程又會引起幾個問題:1.當有大量Http長連接時(如淘寶阿里旺旺)瞎嬉,是不可能為每一個連接創(chuàng)建一個線程的蝎毡。2.線程阻塞時會由用戶態(tài)切換到核心態(tài),保留線程上下文氧枣,這一過程的成本很高沐兵。 3.多線程通常會伴隨著并發(fā)問題。
2.NIO與IO相比便监,優(yōu)勢在哪里
1)IO是面向流的扎谎,就導(dǎo)致他必須從流中讀取一個或多個字節(jié)直到讀取結(jié)束,因為他沒有地方可以緩存茬贵;也不能移動流中前后的數(shù)據(jù)簿透。
? ? 而NIO是面向緩沖區(qū)的,需要時可在緩沖區(qū)中前后移動解藻,增加了處理過程中的靈活性老充。
2)IO是阻塞的,在等待讀取或?qū)懭霑r螟左,縣城會阻塞等待啡浊,無法干別的事。
? ? ? 而NIO是非阻塞的胶背,當一個通道發(fā)出請求進行讀取數(shù)據(jù)時巷嚣,他可以先讀取現(xiàn)在可用的數(shù)據(jù),如不存在可用的數(shù)據(jù)钳吟,他不會阻塞等待廷粒,會去做一些別的事情,比如其他通道的讀寫操作红且。寫也是一樣的坝茎。
3)NIO是基于Selector的,使我們能夠只用一個線程就可以管理多個通道暇番,通過將通道注冊到selector上的方式嗤放。然后它是基于反應(yīng)器模式的,當有事件來臨時壁酬,會注冊在selector中次酌,然后selector會選取合適的通道處理事件。
3.NIO與AIO
都是異步的(指處理I/O事件與I/O處理的異步舆乔?)
NIO對于I/O事件是阻塞的(輪詢)岳服,而對于I/O操作時不阻塞的。
AIO對于I/O事件與處理都是不阻塞的希俩,不用等I/O時間真的發(fā)生就可以做別的事情派阱。
4.NIO可能出現(xiàn)的問題
1)沒有請求時CPU的占用率為100%
當注冊了不感興趣的事件時,又沒有通道去處理斜纪,Selector.select()上就會始終有事件出現(xiàn)(并且沒有I/O處理發(fā)生)贫母,CPU就一直處理了文兑,而此時select()應(yīng)該是阻塞的。
2)由于只使用了一個線程(多個線程也如此)處理用戶請求腺劣,所以要避免線程被阻塞绿贞,解決方法是事件的處理者必須要即刻返回,不能陷入循環(huán)中橘原,否則會影響其他用戶的請求速度籍铁。
3)使用NIO != 高性能,當連接數(shù)<1000趾断,并發(fā)程度不高或者局域網(wǎng)環(huán)境下NIO并沒有顯著的性能優(yōu)勢拒名。
4)NIO并沒有完全屏蔽平臺差異,它仍然是基于各個操作系統(tǒng)的I/O系統(tǒng)實現(xiàn)的芋酌,差異仍然存在增显。使用NIO做網(wǎng)絡(luò)編程構(gòu)建事件驅(qū)動模型并不容易,陷阱重重脐帝。
可以使用成熟的NIO框架同云,如Netty,MINA等堵腹。解決了很多NIO的陷阱炸站,并屏蔽了操作系統(tǒng)的差異,有較好的性能和編程模型疚顷。