Java怎么實現網絡IO高并發編程?
可以用 Java NIO ,是一種同步非阻塞的I/O模型,也是I/O多路復用的基礎。
傳統的BIO里面socket.read(),如果TCP RecvBuffer里沒有數據,函數會一直阻塞,直到收到數據,返回讀到的數據, 如果使用BIO要想要并發處理多個客戶端的i/o,那么會使用多線程模式,一個線程專門處理一個客戶端 io,這種模式隨著客戶端越來越多,所需要創建的線程也越來越多,會急劇消耗系統的性能。
NIO 是基于I/O多路復用實現的,它可以只用一個線程處理多個客戶端I/O,如果你需要同時管理成千上萬的連接,但是每個連接只發送少量數據,例如一個聊天服務器,用NIO實現會更好一些。
BIO、NIO、AIO區別是什么?
- BIO(blocking IO):就是傳統的 java.io 包,它是基于流模型實現的,交互的方式是同步、阻塞方式,也就是說在讀入輸入流或者輸出流時,在讀寫動作完成之前,線程會一直阻塞在那里,它們之間的調用是可靠的線性順序。優點是代碼比較簡單、直觀;缺點是 IO 的效率和擴展性很低,容易成為應用性能瓶頸。
- NIO(non-blocking IO) :Java 1.4 引入的 java.nio 包,提供了 Channel、Selector、Buffer 等新的抽象,可以構建多路復用的、同步非阻塞 IO 程序,同時提供了更接近操作系統底層高性能的數據操作方式。
- AIO(Asynchronous IO) :是 Java 1.7 之后引入的包,是 NIO 的升級版本,提供了異步非堵塞的 IO 操作方式,所以人們叫它 AIO(Asynchronous IO),異步 IO 是基于事件和回調機制實現的,也就是應用操作之后會直接返回,不會堵塞在那里,當后臺處理完成,操作系統會通知相應的線程進行后續的操作。
NIO是怎么實現的?
NIO是一種同步非阻塞的IO模型,所以也可以叫NON-BLOCKINGIO。同步是指線程不斷輪詢IO事件是否就緒,非阻塞是指線程在等待IO的時候,可以同時做其他任務。
同步的核心就Selector(I/O多路復用),Selector代替了線程本身輪詢IO事件,避免了阻塞同時減少了不必要的線程消耗;非阻塞的核心就是通道和緩沖區,當IO事件就緒時,可以通過寫到緩沖區,保證IO的成功,而無需線程阻塞式地等待。
NIO由一個專門的線程處理所有IO事件,并負責分發。事件驅動機制,事件到來的時候觸發操作,不需要阻塞的監視事件。線程之間通過wait,notify通信,減少線程切換。
NIO主要有三大核心部分:Channel(通道),Buffer(緩沖區), Selector。傳統IO基于字節流和字符流進行操作,而NIO基于Channel和Buffer(緩沖區)進行操作,數據總是從通道讀取到緩沖區中,或者從緩沖區寫入到通道中。
Selector(選擇區)用于監聽多個通道的事件(比如:連接打開,數據到達)。因此,單個線程可以監聽多個數據通道。
你知道有哪個框架用到NIO了嗎?
Netty。
Netty 的 I/O 模型是基于非阻塞 I/O 實現的,底層依賴的是 NIO 框架的多路復用器 Selector。采用 epoll 模式后,只需要一個線程負責 Selector 的輪詢。當有數據處于就緒狀態后,需要一個事件分發器(Event Dispather),它負責將讀寫事件分發給對應的讀寫事件處理器(Event Handler)。事件分發器有兩種設計模式:Reactor 和 Proactor,Reactor 采用同步 I/O, Proactor 采用異步 I/O。
Reactor 實現相對簡單,適合處理耗時短的場景,對于耗時長的 I/O 操作容易造成阻塞。Proactor 性能更高,但是實現邏輯非常復雜,適合圖片或視頻流分析服務器,目前主流的事件驅動模型還是依賴 select 或 epoll 來實現。