java是非常繁雜的語言, 比如io就是典型的代表...
首先1.0, 是基于8位位元組流的inputstream和outputstream系列
然後是1.1, 是基于16位的字元流(unicode)的reader和writer系列
下表是對應關系, 其中inputstreamreader和outputstreamwriter, 起到兩個系列之間的适配作用
當然實際的繼承關系比這個複雜的多, 通過裝飾模式, 産生各種io類, 非常繁雜

從1.4開始, java提供new io
其實在new io中主要兩個提升
a, buffer和channel
解決小塊資料傳輸帶來的效率問題, 引入buffer資料結構, 可以批量傳輸以提高效率(這樣更符合底層資料傳輸的方式), 一個挖煤的比喻, 從挖一鏟運一鏟到挖滿一卡車再運出來
b, 對于socket channel加入非阻塞方式
提供一種支援豐富操作的資料結構, 同時雖然對于所有的類型(除bool類型)都有相應的buffer, 但是隻有bytebuffer可以直接被channel讀取, 其餘的都需要在放到channel之前做類型轉換
資料結構
支援操作
下圖以filechannel為例子,
首先channel隻能接收bytebuffer作為write/read的參數
對于其他的buffer必須做類型轉換, 尤其對于charbuffer需要考慮charset的encode/decode
管道很形象, 就是連接配接發送端和接收端之間的媒介
其實就是對于傳統socket或file接口針對bytebuffer的封裝
i/o可以分為廣義的兩大類别:file i/o和stream i/o
是以對應的, channel分為兩類, filechannel和socket相關channel(socketchannel、serversocketchannel和 datagramchannel)
filechannel
filechannel類可以實作常用的read,write以及scatter/gather操作(對于多個buffer的批處理), 同時它也提供了很多專用于檔案的新方法.
檔案通道總是阻塞式的, 因為現代作業系統都有複雜的緩存和預取機制, 是以本地磁盤i/o操作延遲很少
filechannel對象不能直接建立。一個filechannel執行個體隻能通過在一個打開的file對象(randomaccessfile、fileinputstream或 fileoutputstream)上調用getchannel( )方法擷取
filechannel對象是線程安全(thread-safe)
1.4中, java通過filechannel實作了檔案鎖(之前java不支援檔案鎖), 但是這是程序級别鎖, 相同程序中不同線程無法通過檔案鎖進行互斥
socketchannel
新的socket通道類可以運作非阻塞模式, 這個大大提升了java io的性能, 之前隻能使用多線程阻塞的方式來處理并發, 但線程排程的開銷也很高尤其當維護大量線程的時候
全部socket通道類(datagramchannel、socketchannel和serversocketchannel), 分别對應于java.net中的(socket、serversocket和datagramsocket), 并且channel其實就是對他們的封裝
serversocketchannel
從上面兩個例子可以看出channel的使用, 其實和原來的api沒有很大的不同, 關鍵就是支援non-blocking方式
當然還需要selector, 不然非阻塞意義不大, 象c/c++中的select, poll
隻有繼承selectablechannel的channel類才可以被注冊到selector對象上, 是以filechannel對象不是可選擇的, 而所有socketchannel都是可選擇的
selectionkey
代表了selector和selectablechannel的注冊關系
key.attachment(); //傳回selectionkey的attachment,attachment可以在注冊channel的時候指定
key.channel(); // 傳回該selectionkey對應的channel
key.selector(); // 傳回該selectionkey對應的selector
key.interestops(); //傳回代表需要selector監控的io操作的bit mask
key.readyops(); //傳回一個bit mask,代表在相應channel上可以進行的io操作
使用的代碼