<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          NIO-簡(jiǎn)單入門(mén)

          共 2809字,需瀏覽 6分鐘

           ·

          2021-03-01 04:29

          前段時(shí)間在學(xué)習(xí)項(xiàng)目中加入了Dubbo框架,說(shuō)實(shí)話,也就用一下,至于原理,是真的不懂多少。這不,當(dāng)我想要了解Dubbo的原理時(shí),出現(xiàn)了個(gè)陌生詞匯Netty,這下好了,一個(gè)沒(méi)搞懂,又來(lái)一個(gè),那就學(xué)Netty唄,然鵝,是這么簡(jiǎn)單嗎,Netty的底層是NIO,what?啥是NIO鴨,那從這篇開(kāi)始,我就扒一扒NIO那些事,其實(shí)NIO還能往深了扒,什么計(jì)組、操作系統(tǒng)等,奈何我層次不夠,暫且不扒了,等我學(xué)習(xí)下


          先來(lái)說(shuō)下傳統(tǒng)IO(BIO)

          傳統(tǒng)的IO指的是平常用到的那些輸入流/輸出流、字節(jié)流/字符流等,IO是面向流的,單向的,IO的各種流都是阻塞的,即在進(jìn)行read()和write()操作時(shí),線程直接阻塞,該線程將不能做任何事情;當(dāng)來(lái)了新的請(qǐng)求,就只能重新開(kāi)一個(gè)線程來(lái)處理這個(gè)請(qǐng)求,但也同樣會(huì)阻塞

          3aa5b4f21c5968e0c24ea62e98e9ae00.webp


          再說(shuō)下NIO

          NIO是在JDK1.4中新出現(xiàn)的內(nèi)容,其作用和IO是一致的,但是實(shí)現(xiàn)方法和作用是不同的,它是面向緩沖區(qū)、雙向操作的、非阻塞的IO

          b200ea54f42119996bfdd864a63c8075.webp


          IO和NIO的區(qū)別

          IO
          NIO
          面向流
          面向緩沖區(qū)
          阻塞IO
          非阻塞IO
          無(wú)
          Selector選擇器

          面向流與面向緩沖

          IO是面向流進(jìn)行操作的,即每次從流中讀一個(gè)或多個(gè)字節(jié),直到讀取所有的字節(jié),這些數(shù)據(jù)沒(méi)有被緩存起來(lái),需要一次性讀取或?qū)懭耄以诖诉^(guò)程中線程是阻塞狀態(tài);六種的數(shù)據(jù)不能移動(dòng),如果需要移動(dòng),需要將六種的數(shù)據(jù)放到緩沖區(qū)中
          NIO是面向緩沖區(qū)的,即數(shù)據(jù)是被讀取到緩沖區(qū)中,可以基于緩沖區(qū)對(duì)其中的數(shù)據(jù)進(jìn)行移動(dòng)等操作,但是需要判斷該緩沖區(qū)中是否包含所需的數(shù)據(jù),且需要保證當(dāng)緩沖區(qū)內(nèi)數(shù)據(jù)未處理完成時(shí),不能被新的數(shù)據(jù)覆蓋掉

          阻塞IO與非阻塞IO

          IO的各種流都是阻塞的,當(dāng)一個(gè)線程調(diào)用流的read()或write()時(shí),該線程會(huì)被阻塞,直到有一些數(shù)據(jù)被讀取,或數(shù)據(jù)完全寫(xiě)入,期間不能干其他事情,CPU轉(zhuǎn)去處理其他線程,假設(shè)一個(gè)線程監(jiān)聽(tīng)一個(gè)端口,一天只會(huì)有幾次請(qǐng)求進(jìn)來(lái),但是CPU不得不為該線程不斷的做上下文切換,而且大部分切換都是以阻塞告終,這是極其浪費(fèi)系統(tǒng)資源的
          非阻塞IO,是一個(gè)線程在讀操作時(shí),如果沒(méi)有數(shù)據(jù)可讀,就什么都不會(huì)獲取,而不是阻塞;寫(xiě)操作時(shí),再將數(shù)據(jù)寫(xiě)入某個(gè)通道時(shí),不需要等它完全寫(xiě)入,這個(gè)線程就可以去做其他事情了NIO通信是利用事件驅(qū)動(dòng)機(jī)制,而不是監(jiān)聽(tīng)機(jī)制,事件到了再觸發(fā),NIO線程之間通過(guò)wait、notify等方式通知,保證每次上下文切換都有意義,避免系統(tǒng)資源的浪費(fèi)

          選擇器

          Java?NIO的選擇器就是將每個(gè)請(qǐng)求通道都注冊(cè)進(jìn)來(lái),然后對(duì)這些通道進(jìn)行監(jiān)視,由專(zhuān)門(mén)的線程來(lái)選擇通道進(jìn)行執(zhí)行,這種選擇機(jī)制,可以使一個(gè)單獨(dú)的線程很容易的來(lái)管理多個(gè)通道


          NIO的主要元素

          通道(channel):標(biāo)識(shí)打開(kāi)到IO設(shè)備(如:文件、套接字)的鏈接,跟IO中的流差不多,負(fù)責(zé)傳輸

          通道的主要實(shí)現(xiàn)類(lèi)    FileChannel    SocketChannel    ServerSocketChannel    DatagramChannel通道的獲取1)Java針對(duì)支持通道的類(lèi)提供了getChannel()方法  本地IO:    FileInputStream/FileOutputStream    RandomAccessFile  網(wǎng)絡(luò)IO:    Socket    ServerSocket    DatagramSocket(2)在JDK1.7中的NIO.2  針對(duì)各個(gè)通道提供了靜態(tài)方法 open()(3)在JDK1.7中的NIO.2  的Files工具類(lèi)的newByteChannel()

          緩沖區(qū)(Buffer):Java NIO中的Buffer用于和NIO通道進(jìn)行交互。數(shù)據(jù)是從通道讀入緩沖區(qū),從緩沖區(qū)寫(xiě)入到通道中的

          作用:數(shù)據(jù)的操作主要是在緩沖區(qū)中處理,負(fù)責(zé)存儲(chǔ)結(jié)構(gòu):底層是數(shù)組,用來(lái)存儲(chǔ)不同數(shù)據(jù)類(lèi)型的數(shù)據(jù)分類(lèi):ByteBuffer、CharBuffer、ShortBuffer、IntBuffer、LongBuffer、FloatBuffer、DoubleBufferAPI:  allocate():獲取緩沖區(qū)  allocateDirect():分配直接緩沖區(qū)  put():存入數(shù)據(jù)到緩沖區(qū)中  get():獲取緩沖區(qū)中的數(shù)據(jù)??flip():切換讀模式? reset():恢復(fù)到mark位置  hasRemaining():查看緩沖區(qū)中是否還有可操作的數(shù)據(jù)??remaining():獲取緩沖區(qū)中可操作的數(shù)據(jù)??compact():清除已經(jīng)讀過(guò)的數(shù)據(jù)??rewind():可重復(fù)讀,將position置為0四個(gè)核心屬性:??capacity:容量,表示緩沖區(qū)中最大存儲(chǔ)數(shù)據(jù)的容量,一旦聲明不能改變  limit:界限,表示緩沖區(qū)中可以操作數(shù)據(jù)的大小(limit后面的數(shù)據(jù)不能讀寫(xiě))  position:位置,表示緩沖區(qū)中正在操作數(shù)據(jù)的位置  mark:位置,標(biāo)記的位置  0 < mark < position <= limit <= capacity直接緩沖區(qū)和非直接緩沖區(qū)  非直接緩沖區(qū):通過(guò)allocate()方法分配緩沖區(qū),將緩沖區(qū)建立在JVM的內(nèi)存中  直接緩沖區(qū):通過(guò)allocateDirect()方法分配直接緩沖區(qū),將緩沖區(qū)建立在物理內(nèi)存中,可以提高效率獲取直接緩沖區(qū)的方式:  ByteBuffer.allocateDirect  通道內(nèi)存映射文件:    FileChannel inChannel = FileChannel.open(...)    MappedByteBuffer inMapperBuf = inChannel.map(...)?使用Buffer讀寫(xiě)數(shù)據(jù)一般遵循以下四個(gè)步驟:    寫(xiě)入數(shù)據(jù)到Buffer    調(diào)用flip()方法    從Buffer中讀取數(shù)據(jù)    調(diào)用clear()方法或者compact()方法

          4c602252ce190364899554a1fecaa3aa.webp

          選擇器(Selector):管理所有的通道,根據(jù)選擇鍵來(lái)對(duì)應(yīng)處理通道

          Selector可以監(jiān)聽(tīng)的事件類(lèi)型  讀:SelectionKey.OP_READ  寫(xiě):SelectionKey.OP_WRITE  連接:SelectionKey.OP_CONNECT  接收:SelectionKey.OP_ACCEPT監(jiān)聽(tīng)多個(gè)事件可以用?“|”?位或操作符進(jìn)行連接


          今天就先說(shuō)到這里,其實(shí)很多概念看下代碼更容易理解,后面的話會(huì)對(duì)內(nèi)容再進(jìn)行補(bǔ)充,包括學(xué)習(xí)下netty,dubbo等原理


          由于篇幅問(wèn)題,文中不展示大篇幅的代碼,示例代碼均已上傳到碼云,如需更詳細(xì)的了解,請(qǐng)自行下載代碼進(jìn)行測(cè)試

          https://gitee.com/MaYunJerryLee/urmd-code-demo/tree/master/urmd-nio-demo


          瀏覽 83
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  av中文网| 人妻无码免费视频 | 亚洲 成人 在线 | 亚洲wwwwww | 亚洲三级片网站 |