日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

IO与NIO

發(fā)布時(shí)間:2025/3/12 编程问答 18 豆豆
生活随笔 收集整理的這篇文章主要介紹了 IO与NIO 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

1、阻塞與非阻塞

阻塞與非阻塞是描述進(jìn)程在訪問某個(gè)資源時(shí),數(shù)據(jù)是否準(zhǔn)備就緒的的一種處理方式。當(dāng)數(shù)據(jù)沒有準(zhǔn)備就緒時(shí):

  • 阻塞:線程持續(xù)等待資源中數(shù)據(jù)準(zhǔn)備完成,直到返回響應(yīng)結(jié)果。
  • 非阻塞:線程直接返回結(jié)果,不會(huì)持續(xù)等待資源準(zhǔn)備數(shù)據(jù)結(jié)束后才響應(yīng)結(jié)果。

2、同步與異步

  • 同步與異步是指訪問數(shù)據(jù)的機(jī)制,同步一般指主動(dòng)請(qǐng)求并等待IO操作完成的方式。
  • 異步則指主動(dòng)請(qǐng)求數(shù)據(jù)后便可以繼續(xù)處理其它任務(wù),隨后等待IO操作完畢的通知。

老王燒開水:
1、普通水壺煮水,站在旁邊,主動(dòng)的看水開了沒有?同步的阻塞
2、普通水壺煮水,去干點(diǎn)別的事,每過一段時(shí)間去看看水開了沒有,水沒開就走人。 同步非阻塞
3、響水壺煮水,站在旁邊,不會(huì)每過一段時(shí)間主動(dòng)看水開了沒有。如果水開了,水壺自動(dòng)通知他。 異步阻塞
4、響水壺煮水,去干點(diǎn)別的事,如果水開了,水壺自動(dòng)通知他。異步非阻塞

基礎(chǔ)概念

1、傳統(tǒng)BIO模型

傳統(tǒng)BIO是一種同步的阻塞IO,IO在進(jìn)行讀寫時(shí),該線程將被阻塞,線程無法進(jìn)行其它操作。
IO流在讀取時(shí),會(huì)阻塞。直到發(fā)生以下情況:1、有數(shù)據(jù)可以讀取。2、數(shù)據(jù)讀取完成。3、發(fā)生異常

2、偽異步IO模型

以傳統(tǒng)BIO模型為基礎(chǔ),通過線程池的方式維護(hù)所有的IO線程,實(shí)現(xiàn)相對(duì)高效的線程開銷及管理。

3、NIO模型

NIO(JDK1.4)模型是一種同步非阻塞IO,主要有三大核心部分:Channel(通道),Buffer(緩沖區(qū)), Selector(多路復(fù)用器)。傳統(tǒng)IO基于字節(jié)流和字符流進(jìn)行操作,而NIO基于Channel和Buffer(緩沖區(qū))進(jìn)行操作,數(shù)據(jù)總是從通道讀取到緩沖區(qū)中,或者從緩沖區(qū)寫入到通道中。Selector(多路復(fù)用器)用于監(jiān)聽多個(gè)通道的事件(比如:連接打開,數(shù)據(jù)到達(dá))。因此,單個(gè)線程可以監(jiān)聽多個(gè)數(shù)據(jù)通道。
NIO和傳統(tǒng)IO(一下簡(jiǎn)稱IO)之間第一個(gè)最大的區(qū)別是,IO是面向流的,NIO是面向緩沖區(qū)的。 Java IO面向流意味著每次從流中讀一個(gè)或多個(gè)字節(jié),直至讀取所有字節(jié),它們沒有被緩存在任何地方。此外,它不能前后移動(dòng)流中的數(shù)據(jù)。如果需要前后移動(dòng)從流中讀取的數(shù)據(jù),需要先將它緩存到一個(gè)緩沖區(qū)。NIO的緩沖導(dǎo)向方法略有不同。數(shù)據(jù)讀取到一個(gè)它稍后處理的緩沖區(qū),需要時(shí)可在緩沖區(qū)中前后移動(dòng)。這就增加了處理過程中的靈活性。但是,還需要檢查是否該緩沖區(qū)中包含所有您需要處理的數(shù)據(jù)。而且,需確保當(dāng)更多的數(shù)據(jù)讀入緩沖區(qū)時(shí),不要覆蓋緩沖區(qū)里尚未處理的數(shù)據(jù)。
IO的各種流是阻塞的。這意味著,當(dāng)一個(gè)線程調(diào)用read() 或 write()時(shí),該線程被阻塞,直到有一些數(shù)據(jù)被讀取,或數(shù)據(jù)完全寫入。該線程在此期間不能再干任何事情了。 NIO的非阻塞模式,使一個(gè)線程從某通道發(fā)送請(qǐng)求讀取數(shù)據(jù),但是它僅能得到目前可用的數(shù)據(jù),如果目前沒有數(shù)據(jù)可用時(shí),就什么都不會(huì)獲取。而不是保持線程阻塞,所以直至數(shù)據(jù)變的可以讀取之前,該線程可以繼續(xù)做其他的事情。 非阻塞寫也是如此。一個(gè)線程請(qǐng)求寫入一些數(shù)據(jù)到某通道,但不需要等待它完全寫入,這個(gè)線程同時(shí)可以去做別的事情。 線程通常將非阻塞IO的空閑時(shí)間用于在其它通道上執(zhí)行IO操作,所以一個(gè)單獨(dú)的線程現(xiàn)在可以管理多個(gè)輸入和輸出通道(channel)。

NIO優(yōu)點(diǎn):

  • 通過Channel注冊(cè)到Selector上的狀態(tài)來實(shí)現(xiàn)一種客戶端與服務(wù)端的通信。
  • Channel中數(shù)據(jù)的讀取是通過Buffer , 一種非阻塞的讀取方式。
  • Selector 多路復(fù)用器 單線程模型, 線程的資源開銷相對(duì)比較小。
  • Channel(通道)

    傳統(tǒng)IO操作對(duì)read()或write()方法的調(diào)用,可能會(huì)因?yàn)闆]有數(shù)據(jù)可讀/可寫而阻塞,直到有數(shù)據(jù)響應(yīng)。也就是說讀寫數(shù)據(jù)的IO調(diào)用,可能會(huì)無限期的阻塞等待,效率依賴網(wǎng)絡(luò)傳輸?shù)乃俣取W钪匾氖窃谡{(diào)用一個(gè)方法前,無法知道是否會(huì)被阻塞。

    NIO的Channel抽象了一個(gè)重要特征就是可以通過配置它的阻塞行為,來實(shí)現(xiàn)非阻塞式的通道。

    Channel是一個(gè)雙向通道,與傳統(tǒng)IO操作只允許單向的讀寫不同的是,NIO的Channel允許在一個(gè)通道上進(jìn)行讀和寫的操作。

    FileChannel:文件

    SocketChannel:

    ServerSocketChannel:

    DatagramChannel: UDP

    Buffer(緩沖區(qū))

    Bufer顧名思義,它是一個(gè)緩沖區(qū),實(shí)際上是一個(gè)容器,一個(gè)連續(xù)數(shù)組。Channel提供從文件、網(wǎng)絡(luò)讀取數(shù)據(jù)的渠道,但是讀寫的數(shù)據(jù)都必須經(jīng)過Buffer。

    Buffer(緩沖區(qū))

    Buffer緩沖區(qū)本質(zhì)上是一塊可以寫入數(shù)據(jù),然后可以從中讀取數(shù)據(jù)的內(nèi)存。這塊內(nèi)存被包裝成NIO Buffer對(duì)象,并提供了一組方法,用來方便的訪問該模塊內(nèi)存。為了理解Buffer的工作原理,需要熟悉它的三個(gè)屬性:capacity、position和limit。

    position和limit的含義取決于Buffer處在讀模式還是寫模式。不管Buffer處在什么模式,capacity的含義總是一樣的。見下圖:

    capacity、position和limit

    • capacity:作為一個(gè)內(nèi)存塊,Buffer有固定的大小值,也叫作“capacity”,只能往其中寫入capacity個(gè)byte、long、char等類型。一旦Buffer滿了,需要將其清空(通過讀數(shù)據(jù)或者清楚數(shù)據(jù))才能繼續(xù)寫數(shù)據(jù)。
    • position:當(dāng)你寫數(shù)據(jù)到Buffer中時(shí),position表示當(dāng)前的位置。出事的position值為0,當(dāng)寫入一個(gè)字節(jié)數(shù)據(jù)到Buffer中后,position會(huì)向前移動(dòng)到下一個(gè)可插入數(shù)據(jù)的Buffer單元。position最大可為capacity-1。當(dāng)讀取數(shù)據(jù)時(shí),也是從某個(gè)特定位置讀,講Buffer從寫模式切換到讀模式,position會(huì)被重置為0。當(dāng)從Buffer的position處讀取一個(gè)字節(jié)數(shù)據(jù)后,position向前移動(dòng)到下一個(gè)可讀的位置。
    • limit:在寫模式下,Buffer的limit表示你最多能往Buffer里寫多少數(shù)據(jù)。 寫模式下,limit等于Buffer的capacity。當(dāng)切換Buffer到讀模式時(shí), limit表示你最多能讀到多少數(shù)據(jù)。因此,當(dāng)切換Buffer到讀模式時(shí),limit會(huì)被設(shè)置成寫模式下的position值。換句話說,你能讀到之前寫入的所有數(shù)據(jù)(limit被設(shè)置成已寫數(shù)據(jù)的數(shù)量,這個(gè)值在寫模式下就是position)

    Buffer的分配:

    對(duì)Buffer對(duì)象的操作必須首先進(jìn)行分配,Buffer提供一個(gè)allocate(int capacity)方法分配一個(gè)指定字節(jié)大小的對(duì)象。
    向Buffer中寫數(shù)據(jù):寫數(shù)據(jù)到Buffer中有兩種方式:
    1.從channel寫到Buffer

    int bytes = channel.read(buf); //將channel中的數(shù)據(jù)讀取到buf中

    2.通過Buffer的put()方法寫到Buffer

    buf.put(byte); //將數(shù)據(jù)通過put()方法寫入到buf中
    • flip()方法:將Buffer從寫模式切換到讀模式,調(diào)用flip()方法會(huì)將position設(shè)置為0,并將limit設(shè)置為之前的position的值。
      從Buffer中讀數(shù)據(jù):從Buffer中讀數(shù)據(jù)有兩種方式:
      1.從Buffer讀取數(shù)據(jù)到Channel
    int bytes = channel.write(buf); //將buf中的數(shù)據(jù)讀取到channel中

    2.通過Buffer的get()方法讀取數(shù)據(jù)

    byte bt = buf.get(); //從buf中讀取一個(gè)byte
    • rewind()方法:Buffer.rewind()方法將position設(shè)置為0,使得可以重讀Buffer中的所有數(shù)據(jù),limit保持不變。
    • clear()與compact()方法:一旦讀完Buffer中的數(shù)據(jù),需要讓Buffer準(zhǔn)備好再次被寫入,可以通過clear()或compact()方法完成。如果調(diào)用的是clear()方法,position將被設(shè)置為0,limit設(shè)置為capacity的值。但是Buffer并未被清空,只是通過這些標(biāo)記告訴我們可以從哪里開始往Buffer中寫入多少數(shù)據(jù)。如果Buffer中還有一些未讀的數(shù)據(jù),調(diào)用clear()方法將被"遺忘 "。compact()方法將所有未讀的數(shù)據(jù)拷貝到Buffer起始處,然后將position設(shè)置到最后一個(gè)未讀元素的后面,limit屬性依然設(shè)置為capacity。可以使得Buffer中的未讀數(shù)據(jù)還可以在后續(xù)中被使用。
    • mark()與reset()方法:通過調(diào)用Buffer.mark()方法可以標(biāo)記一個(gè)特定的position,之后可以通過調(diào)用Buffer.reset()恢復(fù)到這個(gè)position上。

    Selector(多路復(fù)用器)

    Selector與Channel是相互配合使用的,將Channel注冊(cè)在Selector上之后,才可以正確的使用Selector,但此時(shí)Channel必須為非阻塞模式。Selector可以監(jiān)聽Channel的四種狀態(tài)(Connect、Accept、Read、Write),當(dāng)監(jiān)聽到某一Channel的某個(gè)狀態(tài)時(shí),才允許對(duì)Channel進(jìn)行相應(yīng)的操作。

    • Connect:某一個(gè)客戶端連接成功后
    • Accept:準(zhǔn)備好進(jìn)行連接
    • Read:可讀
    • Write:可寫

    總結(jié)

    以上是生活随笔為你收集整理的IO与NIO的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。