国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Java NIO

這篇具有很好參考價(jià)值的文章主要介紹了Java NIO。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

NIO 簡(jiǎn)介

在傳統(tǒng)的 Java I/O 模型(BIO)中,I/O 操作是以阻塞的方式進(jìn)行的。也就是說(shuō),當(dāng)一個(gè)線程執(zhí)行一個(gè) I/O 操作時(shí),它會(huì)被阻塞直到操作完成。這種阻塞模型在處理多個(gè)并發(fā)連接時(shí)可能會(huì)導(dǎo)致性能瓶頸,因?yàn)樾枰獮槊總€(gè)連接創(chuàng)建一個(gè)線程,而線程的創(chuàng)建和切換都是有開(kāi)銷的。

為了解決這個(gè)問(wèn)題,在 Java1.4 版本引入了一種新的 I/O 模型 — NIO (New IO,也稱為 Non-blocking IO) 。NIO 彌補(bǔ)了同步阻塞 I/O 的不足,它在標(biāo)準(zhǔn) Java 代碼中提供了非阻塞、面向緩沖、基于通道的 I/O,可以使用少量的線程來(lái)處理多個(gè)連接大大提高了 I/O 效率和并發(fā)。

??需要注意:使用 NIO 并不一定意味著高性能,它的性能優(yōu)勢(shì)主要體現(xiàn)在高并發(fā)和高延遲的網(wǎng)絡(luò)環(huán)境下。當(dāng)連接數(shù)較少、并發(fā)程度較低或者網(wǎng)絡(luò)傳輸速度較快時(shí),NIO 的性能并不一定優(yōu)于傳統(tǒng)的 BIO

NIO 核心組件

NIO 主要包括以下三個(gè)核心組件:

  • Buffer(緩沖區(qū)):NIO 讀寫數(shù)據(jù)都是通過(guò)緩沖區(qū)進(jìn)行操作的。讀操作的時(shí)候?qū)?Channel 中的數(shù)據(jù)填充到 Buffer 中,而寫操作時(shí)將 Buffer 中的數(shù)據(jù)寫入到 Channel 中。
  • Channel(通道):Channel 是一個(gè)雙向的、可讀可寫的數(shù)據(jù)傳輸通道,NIO 通過(guò) Channel 來(lái)實(shí)現(xiàn)數(shù)據(jù)的輸入輸出。通道是一個(gè)抽象的概念,它可以代表文件、套接字或者其他數(shù)據(jù)源之間的連接。
  • Selector(選擇器):允許一個(gè)線程處理多個(gè) Channel,基于事件驅(qū)動(dòng)的 I/O 多路復(fù)用模型。所有的 Channel 都可以注冊(cè)到 Selector 上,由 Selector 來(lái)分配線程來(lái)處理事件。

Buffer(緩沖區(qū))

在傳統(tǒng)的 BIO 中,數(shù)據(jù)的讀寫是面向流的, 分為字節(jié)流和字符流。

在 Java 1.4 的 NIO 庫(kù)中,所有數(shù)據(jù)都是用緩沖區(qū)處理的,這是新庫(kù)和之前的 BIO 的一個(gè)重要區(qū)別,有點(diǎn)類似于 BIO 中的緩沖流。NIO 在讀取數(shù)據(jù)時(shí),它是直接讀到緩沖區(qū)中的。在寫入數(shù)據(jù)時(shí),寫入到緩沖區(qū)中。 使用 NIO 在讀寫數(shù)據(jù)時(shí),都是通過(guò)緩沖區(qū)進(jìn)行操作。

Buffer 的子類如下圖所示。其中,最常用的是 ByteBuffer,它可以用來(lái)存儲(chǔ)和操作字節(jié)數(shù)據(jù)。

Java NIO,Java,java,nio,python

你可以將 Buffer 理解為一個(gè)數(shù)組,IntBufferFloatBuffer、CharBuffer 等分別對(duì)應(yīng) int[]、float[]、char[] 等。

為了更清晰地認(rèn)識(shí)緩沖區(qū),我們來(lái)簡(jiǎn)單看看Buffer 類中定義的四個(gè)成員變量:

public abstract class Buffer {
    // Invariants: mark <= position <= limit <= capacity
    private int mark = -1;
    private int position = 0;
    private int limit;
    private int capacity;
}

這四個(gè)成員變量的具體含義如下:

  1. 容量capacity):Buffer可以存儲(chǔ)的最大數(shù)據(jù)量,Buffer創(chuàng)建時(shí)設(shè)置且不可改變;
  2. 界限limit):Buffer 中可以讀/寫數(shù)據(jù)的邊界。寫模式下,limit 代表最多能寫入的數(shù)據(jù),一般等于 capacity(可以通過(guò)limit(int newLimit)方法設(shè)置);讀模式下,limit 等于 Buffer 中實(shí)際寫入的數(shù)據(jù)大小。
  3. 位置position):下一個(gè)可以被讀寫的數(shù)據(jù)的位置(索引)。從寫操作模式到讀操作模式切換的時(shí)候(flip),position 都會(huì)歸零,這樣就可以從頭開(kāi)始讀寫了。
  4. 標(biāo)記mark):Buffer允許將位置直接定位到該標(biāo)記處,這是一個(gè)可選屬性;

并且,上述變量滿足如下的關(guān)系:0 <= mark <= position <= limit <= capacity 。

另外,Buffer 有讀模式和寫模式這兩種模式,分別用于從 Buffer 中讀取數(shù)據(jù)或者向 Buffer 中寫入數(shù)據(jù)。Buffer 被創(chuàng)建之后默認(rèn)是寫模式,調(diào)用 flip() 可以切換到讀模式。如果要再次切換回寫模式,可以調(diào)用 clear() 或者 compact() 方法。

Buffer 對(duì)象不能通過(guò) new 調(diào)用構(gòu)造方法創(chuàng)建對(duì)象 ,只能通過(guò)靜態(tài)方法實(shí)例化 Buffer。

這里以 ByteBuffer為例進(jìn)行介紹:

// 分配堆內(nèi)存
public static ByteBuffer allocate(int capacity);
// 分配直接內(nèi)存
public static ByteBuffer allocateDirect(int capacity);

Buffer 最核心的兩個(gè)方法:

  1. get : 讀取緩沖區(qū)的數(shù)據(jù)
  2. put :向緩沖區(qū)寫入數(shù)據(jù)

除上述兩個(gè)方法之外,其他的重要方法:

  • flip :將緩沖區(qū)從寫模式切換到讀模式,它會(huì)將 limit 的值設(shè)置為當(dāng)前 position 的值,將 position 的值設(shè)置為 0。
  • clear: 清空緩沖區(qū),將緩沖區(qū)從讀模式切換到寫模式,并將 position 的值設(shè)置為 0,將 limit 的值設(shè)置為 capacity 的值。
  • ……

Channel(通道)

Channel 是一個(gè)通道,它建立了與數(shù)據(jù)源(如文件、網(wǎng)絡(luò)套接字等)之間的連接。我們可以利用它來(lái)讀取和寫入數(shù)據(jù),就像打開(kāi)了一條自來(lái)水管,讓數(shù)據(jù)在 Channel 中自由流動(dòng)。

BIO 中的流是單向的,分為各種 InputStream(輸入流)和 OutputStream(輸出流),數(shù)據(jù)只是在一個(gè)方向上傳輸。通道與流的不同之處在于通道是雙向的,它可以用于讀、寫或者同時(shí)用于讀寫。

Channel 與前面介紹的 Buffer 打交道,讀操作的時(shí)候?qū)?Channel 中的數(shù)據(jù)填充到 Buffer 中,而寫操作時(shí)將 Buffer 中的數(shù)據(jù)寫入到 Channel 中

Java NIO,Java,java,nio,python

另外,因?yàn)?Channel 是全雙工的,所以它可以比流更好地映射底層操作系統(tǒng)的 API。特別是在 UNIX 網(wǎng)絡(luò)編程模型中,底層操作系統(tǒng)的通道都是全雙工的,同時(shí)支持讀寫操作。

Channel 的子類如下圖所示。

Java NIO,Java,java,nio,python

其中,最常用的是以下幾種類型的通道:

  • FileChannel:文件訪問(wèn)通道;
  • SocketChannelServerSocketChannel:TCP 通信通道;
  • DatagramChannel:UDP 通信通道;

Java NIO,Java,java,nio,python

Channel 最核心的兩個(gè)方法:

  1. read :讀取數(shù)據(jù)并寫入到 Buffer 中。
  2. write :將 Buffer 中的數(shù)據(jù)寫入到 Channel 中。

這里我們以 FileChannel 為例演示一下是讀取文件數(shù)據(jù)的

RandomAccessFile reader = new RandomAccessFile("/Users/guide/Documents/test_read.in", "r"))
FileChannel channel = reader.getChannel();
ByteBuffer buffer = ByteBuffer.allocate(1024);
channel.read(buffer);

Selector(選擇器)

Selector(選擇器) 是 NIO 中的一個(gè)關(guān)鍵組件,它允許一個(gè)線程處理多個(gè) Channel。Selector 是基于事件驅(qū)動(dòng)的 I/O 多路復(fù)用模型,主要運(yùn)作原理是:通過(guò) Selector 注冊(cè)通道的事件,Selector 會(huì)不斷地輪詢注冊(cè)在其上的 Channel。當(dāng)事件發(fā)生時(shí),比如:某個(gè) Channel 上面有新的 TCP 連接接入、讀和寫事件,這個(gè) Channel 就處于就緒狀態(tài),會(huì)被 Selector 輪詢出來(lái)。Selector 會(huì)將相關(guān)的 Channel 加入到就緒集合中。通過(guò) SelectionKey 可以獲取就緒 Channel 的集合,然后對(duì)這些就緒的 Channel 進(jìn)行響應(yīng)的 I/O 操作。

一個(gè)多路復(fù)用器 Selector 可以同時(shí)輪詢多個(gè) Channel,由于 JDK 使用了 epoll() 代替?zhèn)鹘y(tǒng)的 select 實(shí)現(xiàn),所以它并沒(méi)有最大連接句柄 1024/2048 的限制。這也就意味著只需要一個(gè)線程負(fù)責(zé) Selector 的輪詢,就可以接入成千上萬(wàn)的客戶端。

Selector 可以監(jiān)聽(tīng)以下四種事件類型:

  1. SelectionKey.OP_ACCEPT:表示通道接受連接的事件,這通常用于 ServerSocketChannel。
  2. SelectionKey.OP_CONNECT:表示通道完成連接的事件,這通常用于 SocketChannel。
  3. SelectionKey.OP_READ:表示通道準(zhǔn)備好進(jìn)行讀取的事件,即有數(shù)據(jù)可讀。
  4. SelectionKey.OP_WRITE:表示通道準(zhǔn)備好進(jìn)行寫入的事件,即可以寫入數(shù)據(jù)。

Selector是抽象類,可以通過(guò)調(diào)用此類的 open() 靜態(tài)方法來(lái)創(chuàng)建 Selector 實(shí)例。Selector 可以同時(shí)監(jiān)控多個(gè) SelectableChannelIO 狀況,是非阻塞 IO 的核心。

一個(gè) Selector 實(shí)例有三個(gè) SelectionKey 集合:

  1. 所有的 SelectionKey 集合:代表了注冊(cè)在該 Selector 上的 Channel,這個(gè)集合可以通過(guò) keys() 方法返回。
  2. 被選擇的 SelectionKey 集合:代表了所有可通過(guò) select() 方法獲取的、需要進(jìn)行 IO 處理的 Channel,這個(gè)集合可以通過(guò) selectedKeys() 返回。
  3. 被取消的 SelectionKey 集合:代表了所有被取消注冊(cè)關(guān)系的 Channel,在下一次執(zhí)行 select() 方法時(shí),這些 Channel 對(duì)應(yīng)的 SelectionKey 會(huì)被徹底刪除,程序通常無(wú)須直接訪問(wèn)該集合,也沒(méi)有暴露訪問(wèn)的方法。

簡(jiǎn)單演示一下如何遍歷被選擇的 SelectionKey 集合并進(jìn)行處理:

NIO 零拷貝

零拷貝是提升 IO 操作性能的一個(gè)常用手段,像 ActiveMQ、Kafka 、RocketMQ、QMQ、Netty 等頂級(jí)開(kāi)源項(xiàng)目都用到了零拷貝。

零拷貝是指計(jì)算機(jī)執(zhí)行 IO 操作時(shí),CPU 不需要將數(shù)據(jù)從一個(gè)存儲(chǔ)區(qū)域復(fù)制到另一個(gè)存儲(chǔ)區(qū)域,從而可以減少上下文切換以及 CPU 的拷貝時(shí)間。也就是說(shuō),零拷貝主主要解決操作系統(tǒng)在處理 I/O 操作時(shí)頻繁復(fù)制數(shù)據(jù)的問(wèn)題。零拷貝的常見(jiàn)實(shí)現(xiàn)技術(shù)有: mmap+write、sendfilesendfile + DMA gather copy 。

下圖展示了各種零拷貝技術(shù)的對(duì)比圖:

CPU 拷貝 DMA 拷貝 系統(tǒng)調(diào)用 上下文切換
傳統(tǒng)方法 2 2 read+write 4
mmap+write 1 2 mmap+write 4
sendfile 1 2 sendfile 2
sendfile + DMA gather copy 0 2 sendfile 2

可以看出,無(wú)論是傳統(tǒng)的 I/O 方式,還是引入了零拷貝之后,2 次 DMA(Direct Memory Access) 拷貝是都少不了的。因?yàn)閮纱?DMA 都是依賴硬件完成的。零拷貝主要是減少了 CPU 拷貝及上下文的切換。

Java 對(duì)零拷貝的支持:文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-823147.html

  • MappedByteBuffer 是 NIO 基于內(nèi)存映射(mmap)這種零拷??式的提供的?種實(shí)現(xiàn),底層實(shí)際是調(diào)用了 Linux 內(nèi)核的 mmap 系統(tǒng)調(diào)用。它可以將一個(gè)文件或者文件的一部分映射到內(nèi)存中,形成一個(gè)虛擬內(nèi)存文件,這樣就可以直接操作內(nèi)存中的數(shù)據(jù),而不需要通過(guò)系統(tǒng)調(diào)用來(lái)讀寫文件。
  • FileChanneltransferTo()/transferFrom()是 NIO 基于發(fā)送文件(sendfile)這種零拷貝方式的提供的一種實(shí)現(xiàn),底層實(shí)際是調(diào)用了 Linux 內(nèi)核的 sendfile系統(tǒng)調(diào)用。它可以直接將文件數(shù)據(jù)從磁盤發(fā)送到網(wǎng)絡(luò),而不需要經(jīng)過(guò)用戶空間的緩沖區(qū)

到了這里,關(guān)于Java NIO的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • JAVA NIO簡(jiǎn)解

    JAVA NIO簡(jiǎn)解

    Java nio是Java的一個(gè)新的輸入輸出(NewInput/Output)API,它提供了一些高效的數(shù)據(jù)處理方式,如緩沖區(qū)(buffers)、字符集(charsets)、通道(channels)和選擇器(selectors)。 Java NIO可以實(shí)現(xiàn)非阻塞式的多路復(fù)用輸入輸出,提高了程序的性能和可擴(kuò)展性。Java nio是在Java 1.4版本中引入

    2023年04月16日
    瀏覽(20)
  • Java NIO

    Java NIO

    在傳統(tǒng)的 Java I/O 模型(BIO)中,I/O 操作是以阻塞的方式進(jìn)行的。也就是說(shuō), 當(dāng)一個(gè)線程執(zhí)行一個(gè) I/O 操作時(shí),它會(huì)被阻塞直到操作完成 。這種阻塞模型在處理多個(gè)并發(fā)連接時(shí)可能會(huì)導(dǎo)致性能瓶頸,因?yàn)樾枰獮槊總€(gè)連接創(chuàng)建一個(gè)線程,而線程的創(chuàng)建和切換都是有開(kāi)銷的。 為了

    2024年01月25日
    瀏覽(21)
  • 淺談Java NIO

    淺談Java NIO

    Java NIO(New Input/Output)是Java平臺(tái)上一種全新的IO API,相較于傳統(tǒng)的Java I/O(也稱為BIO,阻塞I/O),NIO引入了非阻塞I/O和通道(Channel)的概念,以及緩沖區(qū)(Buffer)和選擇器(Selector)機(jī)制,大大提升了系統(tǒng)的并發(fā)處理能力和性能。以下是對(duì)NIO實(shí)現(xiàn)原理的關(guān)鍵點(diǎn)概述: 非阻塞

    2024年04月17日
    瀏覽(17)
  • BIO、NIO、IO多路復(fù)用模型詳細(xì)介紹&Java NIO 網(wǎng)絡(luò)編程

    BIO、NIO、IO多路復(fù)用模型詳細(xì)介紹&Java NIO 網(wǎng)絡(luò)編程

    上文介紹了網(wǎng)絡(luò)編程的基礎(chǔ)知識(shí),并基于 Java 編寫了 BIO 的網(wǎng)絡(luò)編程。我們知道 BIO 模型是存在巨大問(wèn)題的,比如 C10K 問(wèn)題,其本質(zhì)就是因其阻塞原因,導(dǎo)致如果想要承受更多的請(qǐng)求就必須有足夠多的線程,但是足夠多的線程會(huì)帶來(lái)內(nèi)存占用問(wèn)題、CPU上下文切換帶來(lái)的性能問(wèn)題

    2024年02月14日
    瀏覽(30)
  • Java-NIO介紹

    Java NIO(New IO)是Java提供的一種用于進(jìn)行高效IO操作的API。NIO庫(kù)允許開(kāi)發(fā)人員使用非阻塞、事件驅(qū)動(dòng)的方式進(jìn)行IO操作,從而提高程序的性能和可擴(kuò)展性。 相對(duì)于傳統(tǒng)的Java IO(InputStream/OutputStream)來(lái)說(shuō),Java NIO引入了以下幾個(gè)新的概念和組件: 通道(Channel):數(shù)據(jù)源和目的地

    2024年02月11日
    瀏覽(19)
  • Java NIO FileChannel:BIO與NIO區(qū)別、核心組成部分和常用方方法

    深入探討Java NIO中的FileChannel,包括BIO與NIO的區(qū)別、NIO的核心組成部分(Channels、Buffers、Selectors)、FileChannel的常用方法以及示例代碼。了解如何使用FileChannel進(jìn)行文件數(shù)據(jù)讀寫操作。

    2024年01月25日
    瀏覽(25)
  • 【java】BIO、NIO、AIO

    同步阻塞IO,使用BIO讀取數(shù)據(jù)時(shí),線程會(huì)阻塞住,并且需要線程主動(dòng)去查詢是否有數(shù)據(jù)可讀,并且需要處理完一個(gè)Socket之后才能處理下一個(gè)Socket 在這種模型下,每個(gè) I/O 操作都會(huì)阻塞當(dāng)前線程,直到操作完成才會(huì)返回。這意味著當(dāng)一個(gè)線程執(zhí)行 I/O 操作時(shí),它會(huì)被阻塞,無(wú)法執(zhí)

    2024年04月10日
    瀏覽(23)
  • Java 中的 IO 和 NIO

    Java IO(Input/Output)流是用于處理輸入和輸出數(shù)據(jù)的機(jī)制。它提供了一種標(biāo)準(zhǔn)化的方式來(lái)讀取和寫入數(shù)據(jù),可以與文件、網(wǎng)絡(luò)、標(biāo)準(zhǔn)輸入輸出等進(jìn)行交互。 Java IO流主要分為兩個(gè)流模型:字節(jié)流(Byte Stream)和字符流(Character Stream)。 字節(jié)流(Byte Stream) InputStream:字節(jié)輸入流

    2024年02月10日
    瀏覽(23)
  • java網(wǎng)絡(luò)編程——NIO架構(gòu)

    java網(wǎng)絡(luò)編程——NIO架構(gòu)

    目錄 1.什么是NIO 2.NIO結(jié)構(gòu) 3.基于NIO下的聊天系統(tǒng)實(shí)現(xiàn) 4.Netty NIO:java non-blocking IO,同步非阻塞IO。 BIO是阻塞IO,即每一個(gè)事件都需要分配一個(gè)進(jìn)程給他,如果客戶端沒(méi)有連接上,則一直阻塞等待。 而NIO,異步 I/O 是一種沒(méi)有阻塞地讀寫數(shù)據(jù)的方法:該架構(gòu)下我們可以注冊(cè)對(duì)特定

    2023年04月26日
    瀏覽(23)
  • java nio中的ByteBuffer擴(kuò)展

    在jdk1.4之前對(duì)于輸入輸出只能使用InPutStream和outPutSream這類傳統(tǒng)io模型,在jdk1.4之后新增了nio,什么是nio?nio是new input/output 的簡(jiǎn)稱,nio的效率要比傳統(tǒng)io效率高,主要原因就是nio利用了系統(tǒng)底層的零拷貝技術(shù)和多路復(fù)用技術(shù)。 NIO有三個(gè)核心概念 1、Channal通道 2、Buffer緩沖 3、Se

    2023年04月16日
    瀏覽(18)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包