系列文章:
系列文章:
Android 網絡系列更新計劃
Android NIO 系列教程(一) NIO概述
Android NIO 系列教程(二) – Channel
Android NIO 系列教程(三) – Buffer
根據 英語原文 翻譯過來,添加自己一些理解,英語好的,也可以直接閱讀原文。
在 Socket 的教程 Android Socket 系列更新計劃中,我們已經學習了 Socket 的基本使用和一些案例;但在多人聊天室中,我們已經知道,在百萬級別的客戶端連接時,無論服務端怎麼優化,線程和IO阻塞問題已經存在;
一、NIO介紹
所以,這裏我們學習一下 JDK1.4之後引入的非阻塞 IO – NIO;他們的區別如下:
- 阻塞與非阻塞: 傳統 IO 在讀寫時是阻塞的,即當我們在 write 或者 read 的時候,線程是阻塞的,在此期間,線程不能做其他事,直到文件的字節被全部讀取完成,線程纔回復空閒狀態。而非阻塞則表示請求一個數據寫入通道,在其期間線程還能去處理其他事,大大增大了線程的利用率;
- 面向對象不同:傳統IO面向字節流,而NIO則面向緩衝流;Java IO面向流意味着每次從流中讀一個或多個字節,直至讀取所有字節,它們沒有被緩存在任何地方。此外,它不能前後移動流中的數據。如果需要前後移動從流中讀取的數據,需要先將它緩存到一個緩衝區;NIO則不同,在讀寫時數據存在一個 buffer 緩衝區中,可以前後移動,處理數據時只需要處理Buffer的數據即可,大大增大了靈活性。
- Selectors:相較於傳統IO,NIO 由 Selector 選擇器來處理事物;即用一個線程來監視多路通道,大大減少了線程開銷;後面介紹NIO模式,我們再來討論 selector 。
Java NIO 由以下核心部分組成:
- Channel
- Buffer
- Selectors
1.1、Channel & Buffer
基本上,所有NIO的IO都從一個 Channel 通道開始的,Channel 有點像流,可以從一個 Channel 讀取數據到Buffer,也可以從Buffer 讀數據到 Channel,如下圖:
Channel 的種類有以下幾種,包含了 TCP+UDP,網絡和文件類型:
- FileChannel
- DatagramChannel
- SocketChannel
- ServerSocketChannel
Buffer 的類型包含以下幾種基礎類型:
- ByteBuffer
- CharBuffer
- DoubleBuffer
- FloatBuffer
- IntBuffer
- LongBuffer
- ShortBuffer
Java 的NIO還包含 MappedByteBuffer , 用於內存映射,這裏沒用到,就不先討論了。
1.2、Selectors
Selectors 允許單個線程處理多個Channel ,如果你的app打開了多個連接,但每個連接的流量都很低的情況下,使用 selector 是個不錯的選擇,比如聊天室。
下面是是一個 selector 連接 三個 channel 的案例:
使用 selector 之前,得向 selector 註冊 channel,然後調用它的 select() 方法;該方法會一直阻塞,直到有註冊channel準備就緒,一旦該方法有返回事件,則該線程就可以去處理這些事件,包括新連接、數據接收等。