IO

1萤厅、文件IO


JAVA-IO.png

使用 Off Heap 堆外內(nèi)存,減少了堆內(nèi)向堆外拷貝過程蜜笤,效率要高一些濒蒋,

堆內(nèi):JVM 堆內(nèi)內(nèi)存。

堆外:JVM堆外把兔,JAVA 進程堆內(nèi)沪伙。

mapped映射:是 mmap 調(diào)用的一個進程和內(nèi)核共享的內(nèi)存區(qū)域,且這個內(nèi)存區(qū)域是 PageCache 到文件的映射县好。

性能表現(xiàn) mapped > off heap > on heep围橡。

Java 普通IO,每次調(diào)用寫操作聘惦,都會向 OS PageCache 溢寫某饰,而 Buffered IO(8KB)儒恋,向其寫入時,僅寫入到 JVM 內(nèi)存黔漂,知道寫滿之后诫尽,才會溢寫到 PageCache。

對比來看炬守,Buffered 少了很多 system callint 0x80牧嫉,因此效率高很多。

ByteBuffer

內(nèi)存分配

  • 堆內(nèi)分配:ByteBuffer.allocate(1024)
  • 堆外分配:ByteBuffer.allocateDirect(1024)

函數(shù)

  • put:寫入數(shù)據(jù)减途,并移動 position 指針酣藻。
ByteBuffer-PUT.png
  • flip:由寫模式切換到讀模式。讀模式下調(diào)用鳍置,會使 limit 指向當(dāng)前 position 位置辽剧,造成指針錯亂。
ByteBuffer-FLIP.png
  • get:讀取數(shù)據(jù)税产,并移動 position 指針怕轿。讀操作應(yīng)在 flip 操作后執(zhí)行,否則可能讀取到錯誤數(shù)據(jù)辟拷。
ByteBuffer-GET.png
  • compact:壓縮數(shù)據(jù)撞羽,并切換到寫模式。如果在寫模式調(diào)用衫冻,數(shù)據(jù)會錯亂诀紊,因為 limit 指向 了 tail。
ByteBuffer-COMPACT.png
  • mark - reset:標(biāo)記 position 位置隅俘,重置 position 到 mark 位置邻奠,不會切換讀寫模式,讀寫模式都可用为居。
ByteBuffer-MARK-RESET.png
  • slice:創(chuàng)建一個新的字節(jié)緩沖區(qū)惕澎,其內(nèi)容是給定緩沖區(qū)內(nèi)容的共享子序列。

    新緩沖區(qū)的內(nèi)容將從該緩沖區(qū)的當(dāng)前位置開始颜骤。對該緩沖區(qū)內(nèi)容的更改將在新緩沖區(qū)中可見,反之亦然捣卤。這兩個緩沖區(qū)的位置忍抽,限制和標(biāo)記值將是獨立的。

    新緩沖區(qū)的位置將為零董朝,其容量和限制將為該緩沖區(qū)中剩余的浮點數(shù)鸠项,并且其標(biāo)記將不確定。當(dāng)且僅當(dāng)該緩沖區(qū)是直接緩沖區(qū)時子姜,新緩沖區(qū)才是直接緩沖區(qū)祟绊;當(dāng)且僅當(dāng)該緩沖區(qū)是只讀緩沖區(qū)時,新緩沖區(qū)才是只讀緩沖區(qū)。

  • rewind:清除 mark 標(biāo)記牧抽,并將 position 指針 重置為0嘉熊。

  • clear:重置緩沖區(qū),清除 mark 標(biāo)記扬舒,重置 position 指針阐肤,重置 limit 指針,回歸寫模式讲坎。

RandomAccessFile

Mode 說明
r 打開文件僅僅是為了讀取數(shù)據(jù)孕惜,如果嘗試調(diào)用任何寫入數(shù)據(jù)的操作都會造成返回IOException錯誤信息的問題。
rw 打開文件用于讀寫兩種操作晨炕,如果文件本身并不存在衫画,則會創(chuàng)建一個全新的文件。
rwd 打開文件用于讀寫兩種操作瓮栗,這點和 rw 的操作完全一致削罩,但是只會在 cache 滿,或者調(diào)用 RandomAccessFile.close() 的時候才會執(zhí)行內(nèi)容同步操作遵馆。
rws 在 rwd 的基礎(chǔ)上對內(nèi)容同步的要求更加嚴(yán)苛鲸郊,每write修改一個byte都會直接修改到磁盤中。
RandomAccessFile raf = new RandomAccessFile(new File("/path/to/file"), "rw");
// 寫數(shù)據(jù)
raf.write(new byte[5]);
// 移動指針
raf.seek(0L);
// 跳過字節(jié)
raf.skipBytes(1);
// 讀數(shù)據(jù) off:輸入數(shù)組偏移量 len:讀字節(jié)數(shù)
raf.read(new byte[10], 0, 10);
// 關(guān)閉并寫盤
raf.close();

FileChannel

RandomAccessFile raf = new RandomAccessFile(new File("/path/to/file"), "rw");
FileChannel channel = raf.getChannel();
// Zero Copy
channel.transferTo(position, count, target);
channel.transferFrom(src, position, count);

MappedByteBuffer

  • 不通過系統(tǒng)調(diào)用货邓,數(shù)據(jù)直接到達(dá) PageCache秆撮。
  • mmap 的內(nèi)存映射,依然受內(nèi)核 pageCache 體系所約束换况。
  • DirectIO 是忽略內(nèi)核的 PageCache职辨,Java 沒有直接使用內(nèi)核 DirectIO 的支持,需要C程序JNI擴展庫戈二。
  • MappedByteBuffer 只是交給程序開辟自己的字節(jié)數(shù)組充當(dāng) PageCache舒裤,仍需要程序動用代碼維護一致性/Dirty等一系列問題。
MapMode 說明
FileChannel.MapMpde.READ_ONLY Mode for a read-only mapping. 只讀模式觉吭。
FileChannel.MapMpde.READ_WRITE Mode for a read/write mapping. 讀寫模式腾供。
FileChannel.MapMpde.PRIVATE Mode for a private (copy-on-write) mapping. 堆內(nèi)存更改不會寫入文件。
RandomAccessFile raf = new RandomAccessFile(new File("/path/to/file"), "rw");
FileChannel channel = raf.getChannel();

MappedByteBuffer map = channel.map(FileChannel.MapMode.READ_WRITE, 0, 4090);
// 其余操作函數(shù)可參考 ByteBuffer
map.put(new byte[10]);
// PC數(shù)據(jù)寫入存儲設(shè)備
buffer.force();

2鲜滩、TCP網(wǎng)絡(luò)IO


服務(wù)端 LISTEN 狀態(tài)端口號伴鳖,最多65535個。

服務(wù)端無需為 Client 連接分配隨機端口號徙硅,只要四元組(源IP榜聂、源端口、目標(biāo)IP嗓蘑、目標(biāo)端口)不同须肆,就可以確定一個連接匿乃。

三次握手是內(nèi)核級的,ServerSocket 啟動之后豌汇,客戶端連接時幢炸,無需等待 server.accept() 即可完成三次握手,建立連接瘤礁。

因為客戶端連接是連接層業(yè)務(wù)阳懂,不需要等待應(yīng)用層響應(yīng)。

客戶端連接建立之后柜思,server.accept() 之前岩调,OS 僅僅開辟資源,并不會分配 FD赡盘。

當(dāng) server.accept() 之后号枕,OS 才會創(chuàng)建 FD,F(xiàn)D 在 Java 中體現(xiàn)為 Socket 對象陨享。

ServerSocket配置

  • BACK_LOG:未 accept 的連接隊列長度葱淳,超過此數(shù)量的連接,在 netstat 中體現(xiàn)為 SYN_RECV 狀態(tài)抛姑。

  • SO_TIMEOUT:server.accept() 超時配置赞厕,超過閾值未收到連接請求,會跑出 SocketTimeoutException 異常定硝,但并不會造成 server 崩潰皿桑。

  • RECEIVE_BUFFER_SIZE:最大接收窗口,默認(rèn) 8192蔬啡。最終數(shù)值由三次握手之后雙方最小緩沖區(qū)為基準(zhǔn)诲侮。

  • REUSE_ADDRESS:端口重用。如果禁用箱蟆,在程序關(guān)閉后沟绪,端口可能會繼續(xù)占用一段時間,如果此時立刻重啟程序空猜,會拋出異常绽慈。

    綁定到相同端口的程序,必須全部啟用該配置辈毯,才可重用端口久信,設(shè)置此參數(shù)必須在程序綁定到一個本地端口之前調(diào)用。

Socker配置

  • KEEP_ALIVE:TCP連接空閑時是否需要向?qū)Ψ桨l(fā)送探測包漓摩,依賴于底層的TCP模塊實現(xiàn)的,Java中只能設(shè)置是否開啟入客,不能設(shè)置其詳細(xì)參數(shù)管毙,依賴于系統(tǒng)配置腿椎。

  • SO_TIMEOUT:在與此 Socket 關(guān)聯(lián)的 InputStream 上調(diào)用 read() 將只阻塞此時間長度,超時將引發(fā) SocketTimeoutException夭咬,但 socket 不會崩潰啃炸。

  • OOB_INLINE:TCP的緊急指針,一般不建議使用卓舵,且不同的TCP/IP實現(xiàn)不同南用。

    雖然 Socket.sendUrgentData() 的參數(shù)是 int 類型,但只有這個int類型的低字節(jié)被發(fā)送掏湾,其它的三個字節(jié)被忽略裹虫。

    客戶端和服務(wù)端必須同時開啟,否則無法使用 Socket.sendUrgentData() 發(fā)送數(shù)據(jù)融击。

  • RECEIVE_BUFFER_SIZE:最大接收窗口筑公,默認(rèn) 8192。最終數(shù)值由三次握手之后雙方最小緩沖區(qū)為基準(zhǔn)尊浪。

  • SEND_BUFFER_SIZE:最大發(fā)送窗口匣屡,默認(rèn) 8192。最終數(shù)值由三次握手之后雙方最小緩沖區(qū)為基準(zhǔn)拇涤。

  • REUSE_ADDRESS:端口重用捣作。如果禁用,在程序關(guān)閉后鹅士,端口可能會繼續(xù)占用一段時間券躁,如果此時立刻重啟程序,會拋出異常如绸。

    綁定到相同端口的程序嘱朽,必須全部啟用該配置,才可重用端口怔接,設(shè)置此參數(shù)必須在程序綁定到一個本地端口之前調(diào)用搪泳。

  • SO_LINGER:控制 Socket 關(guān)閉行為,

    • 默認(rèn)情況執(zhí)行 Socket.close() 立即返回扼脐,但底層的連接不會立即關(guān)閉岸军,會延遲一段時間,直到數(shù)據(jù)發(fā)送完成瓦侮,才會真正的關(guān)閉 Socket艰赞,斷開連接。
    • Socket.setSoLinger(true, 0):執(zhí)行 Socket.close() 會立即返回肚吏,底層 Socket 立即關(guān)閉方妖,所有未發(fā)送數(shù)據(jù)被丟棄。
    • Socket.setSoLinger(true, 3600):執(zhí)行 Socket.close() 會進入阻塞狀態(tài)罚攀,底層 Socket 嘗試發(fā)送剩余數(shù)據(jù)党觅,直到如下條件解除阻塞狀態(tài):
      1. 剩余數(shù)據(jù)發(fā)送完成雌澄。
      2. 剩余數(shù)據(jù)未發(fā)送完成,但阻塞超過 3600毫秒杯瞻,立即返回镐牺,且丟棄剩余數(shù)據(jù)。
  • TCP_NO_DELAY:默認(rèn) false魁莉,為啟用 Nagle算法睬涧。Nagle 算法的立意是,避免網(wǎng)絡(luò)中充塞小封包旗唁,提高網(wǎng)絡(luò)的利用率畦浓。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市逆皮,隨后出現(xiàn)的幾起案子宅粥,更是在濱河造成了極大的恐慌,老刑警劉巖电谣,帶你破解...
    沈念sama閱讀 219,270評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件秽梅,死亡現(xiàn)場離奇詭異,居然都是意外死亡剿牺,警方通過查閱死者的電腦和手機企垦,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,489評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來晒来,“玉大人钞诡,你說我怎么就攤上這事∨缺溃” “怎么了荧降?”我有些...
    開封第一講書人閱讀 165,630評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長攒读。 經(jīng)常有香客問我朵诫,道長,這世上最難降的妖魔是什么薄扁? 我笑而不...
    開封第一講書人閱讀 58,906評論 1 295
  • 正文 為了忘掉前任剪返,我火速辦了婚禮,結(jié)果婚禮上邓梅,老公的妹妹穿的比我還像新娘脱盲。我一直安慰自己,他們只是感情好日缨,可當(dāng)我...
    茶點故事閱讀 67,928評論 6 392
  • 文/花漫 我一把揭開白布钱反。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪面哥。 梳的紋絲不亂的頭發(fā)上乙各,一...
    開封第一講書人閱讀 51,718評論 1 305
  • 那天,我揣著相機與錄音幢竹,去河邊找鬼。 笑死恩静,一個胖子當(dāng)著我的面吹牛焕毫,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播驶乾,決...
    沈念sama閱讀 40,442評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼邑飒,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了级乐?” 一聲冷哼從身側(cè)響起疙咸,我...
    開封第一講書人閱讀 39,345評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎风科,沒想到半個月后撒轮,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,802評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡贼穆,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,984評論 3 337
  • 正文 我和宋清朗相戀三年题山,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片故痊。...
    茶點故事閱讀 40,117評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡顶瞳,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出愕秫,到底是詐尸還是另有隱情慨菱,我是刑警寧澤,帶...
    沈念sama閱讀 35,810評論 5 346
  • 正文 年R本政府宣布戴甩,位于F島的核電站符喝,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏等恐。R本人自食惡果不足惜洲劣,卻給世界環(huán)境...
    茶點故事閱讀 41,462評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望课蔬。 院中可真熱鬧囱稽,春花似錦、人聲如沸二跋。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,011評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽扎即。三九已至吞获,卻和暖如春况凉,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背各拷。 一陣腳步聲響...
    開封第一講書人閱讀 33,139評論 1 272
  • 我被黑心中介騙來泰國打工刁绒, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人烤黍。 一個月前我還...
    沈念sama閱讀 48,377評論 3 373
  • 正文 我出身青樓知市,卻偏偏與公主長得像,于是被迫代替她去往敵國和親速蕊。 傳聞我的和親對象是個殘疾皇子嫂丙,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,060評論 2 355

推薦閱讀更多精彩內(nèi)容