傳統服務器實現是BIO和多線程方式(一個socket一個線程),這種模式又很大的限制,首先BIO阻塞線程嚴重影響服務器性能,以及多線程的方式,當併發線程數大起來後會致使系統頻繁的在線程以前切換,一樣會影響系統性能。
Java1.4後引入Nio API,經過使用非阻塞實現IO快速讀寫,爲高併發服務器提供了很好的解決方案。
Java Nio API由Buffer, Channel和Selector組成,Java只是提供了一個規範,部分方法並未實現,Sun Nio則實現了Java Nio。
Buffer做爲緩衝區將數據緩存起來,從而作到數據的非阻塞讀寫;Channel則對應文件句柄,包括file,socket等,每一個Channel自帶Buffer,Channel上的讀寫數據所有存放到Buffer中,Channel和Buffer的組合實現了io的非堵塞;Selector則做爲選擇器,負責監聽Channel上的事件,一個Selector能夠管理多個Channel,實現多路複用。
linux
- Buffer:
關鍵類:
ByteBuffer
CharBuffer
IntBuffer
FloatBuffer
DoubleBuffer
LongBuffer
MappedByteBuffer
Buffer按照分配方式又分爲DirectxxxBuffer, HeapxxxBuffer。DirectxxxBuffer是直接分配JVM外的內存,HeapxxxBuffer則是分配JVM堆內存。
結構:
方法:
get( ) 從Buffer中讀取數據
put( ) 寫數據到Buffer中
flip( ) 將Buffer從寫模式切換到讀模式
rewind( ) 重置position和mark用於重寫數據或者重複讀
clear( ) 清空整個緩衝區
compact( ) 清除已經讀過的緩衝區
- Channel:
關鍵類:
SocketChannel
FileChannel
DatagramChannel
ServerSocketChannel
Channel是對文件句柄的封裝,每一個Channel對應一個句柄,包括file, socket等。
Channel配合Buffer使用,能夠從Channel中讀取Buffer和寫入Buffer。
方法:
read(buffer) 從Channel中讀取數據到buffer中
write(buffer) 將buffer中的數據寫入到Channel中
- Selector: 關鍵類: Selector SelectorProvider Selector用於實現多路複用,能夠註冊多個Channel,經過select方法返回本身感興趣的事件,Selector底層在linux上經過epoll實現。 Selector配合SelectionKey使用,SelectionKey記錄了事件的類型和事件的Channel。 方法: select( ) 阻塞等待Selector上的事件 selectdKeys( ) 返回Selector上的事件