摘要:該線程在此期間不能再干任何事情了。線程通訊線程之間通過等方式通訊。選擇器傳統(tǒng)的模式會(huì)基于服務(wù)器會(huì)為每個(gè)客戶端請(qǐng)求建立一個(gè)線程由該線程多帶帶負(fù)貴處理一個(gè)客戶請(qǐng)求。
本文是對(duì)NIO知識(shí)的歸納與整理
1.阻塞與同步1)阻塞(Block)和非租塞(NonBlock):
阻塞和非阻塞是進(jìn)程在訪問數(shù)據(jù)的時(shí)候,數(shù)據(jù)是否準(zhǔn)備就緒的一種處理方式,當(dāng)數(shù)據(jù)沒有準(zhǔn)備的時(shí)候阻塞:往往需要等待缞沖區(qū)中的數(shù)據(jù)準(zhǔn)備好過后才處理其他的事情,否則一直等待在那里。
非阻塞:當(dāng)我們的進(jìn)程訪問我們的數(shù)據(jù)緩沖區(qū)的時(shí)候,如果數(shù)據(jù)沒有準(zhǔn)備好則直接返回,不會(huì)等待。如果數(shù)據(jù)已經(jīng)準(zhǔn)備好,也直接返回
2)同步(Synchronization)和異步(Async)的方式:
同步和異步都是基于應(yīng)用程序私操作系統(tǒng)處理IO事件所采用的方式,比如同步:是應(yīng)用程序要直接參與IO讀寫的操作。異步:所有的IO讀寫交給搡作系統(tǒng)去處理,應(yīng)用程序只需要等待通知。
同步方式在處理IO事件的時(shí)候,必須阻塞在某個(gè)方法上靣等待我們的IO事件完成(阻塞IO事件或者通過輪詢IO事件的方式).對(duì)于異步來說,所有的IO讀寫都交給了搡作系統(tǒng)。這個(gè)時(shí)候,我們可以去做其他的事情,并不拓要去完成真正的IO搡作,當(dāng)搡作完成IO后.會(huì)給我們的應(yīng)用程序一個(gè)通知
同步:阻塞到IO事件,阻塞到read成則write。這個(gè)時(shí)候我們就完全不能做自己的事情,讓讀寫方法加入到線程里面,然后阻塞線程來實(shí)現(xiàn),對(duì)線程的性能開銷比較大,
2.BIO與NIO對(duì)比block IO與Non-block IO
1)區(qū)別
IO模型IONIO
方式從硬盤到內(nèi)存從內(nèi)存到硬盤
通信面向流(鄉(xiāng)村公路)面向緩存(高速公路,多路復(fù)用技術(shù))
處理阻塞IO(多線程)非阻塞IO(反應(yīng)堆Reactor)
觸發(fā)無選擇器(輪詢機(jī)制)
2)面向流與面向緩沖
Java NIO和IO之間第一個(gè)最大的區(qū)別是,IO是面向流的.NIO是面向緩沖區(qū)的。Java IO面向流意味著毎次從流中讀一個(gè)成多個(gè)字節(jié),直至讀取所有字節(jié),它們沒有被緩存在任何地方,此外,它不能前后移動(dòng)流中的數(shù)據(jù)。如果需要前后移動(dòng)從流中讀取的教據(jù),需要先將它緩存到一個(gè)緩沖區(qū)。Java NIO的緩沖導(dǎo)向方法略有不同。數(shù)據(jù)讀取到一個(gè)它稍后處理的緩沖區(qū),霱要時(shí)可在緩沖區(qū)中前后移動(dòng)。這就增加了處理過程中的靈活性。但是,還需要檢查是否該緩沖區(qū)中包含所有您需要處理的數(shù)裾。而且,需確保當(dāng)更多的數(shù)據(jù)讀入緩沖區(qū)時(shí),不要覆蓋緩沖區(qū)里尚未處理的數(shù)據(jù)。
3)阻塞與非阻塞
Java IO的各種流是阻塞的。這意味著,當(dāng)一個(gè)線程調(diào)用read() 或 write()時(shí),該線程被阻塞,直到有一些數(shù)據(jù)被讀取,或數(shù)據(jù)完全寫入。該線程在此期間不能再干任何事情了。 Java 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è)多帶帶的線程現(xiàn)在可以管理多個(gè)輸入和輸出通道(channel)。
4)選擇器(Selector)
Java NIO的選擇器允許一個(gè)多帶帶的線程來監(jiān)視多個(gè)輸入通道,你可以注冊(cè)多個(gè)通道使用一個(gè)選擇器,然后使用一個(gè)多帶帶的線程來“選擇"通道:這些通里已經(jīng)有可以處理的褕入,或者選擇已準(zhǔn)備寫入的通道。這選懌機(jī)制,使得一個(gè)多帶帶的線程很容易來管理多個(gè)通道。
5)NIO和BIO讀取文件
BIO讀取文件
BIO從一個(gè)阻塞的流中一行一行的讀取數(shù)據(jù)
NIO讀取文件
通道是數(shù)據(jù)的載體,buffer是存儲(chǔ)數(shù)據(jù)的地方,線程每次從buffer檢查數(shù)據(jù)通知給通道
6)處理數(shù)據(jù)的線程數(shù)
NIO:一個(gè)線程管理多個(gè)連接
BIO:一個(gè)線程管理一個(gè)連接
3.NIO簡介在Java1.4之前的I/O系統(tǒng)中,提供的都是面向流的I/O系統(tǒng),系統(tǒng)一次一個(gè)字節(jié)地處理數(shù)據(jù),一個(gè)輸入流產(chǎn)生一個(gè)字節(jié)的數(shù)據(jù),一個(gè)輸出流消費(fèi)一個(gè)字節(jié)的數(shù)據(jù),面向流的I/O速度非常慢,而在Java 1.4中推出了NIO,這是一個(gè)面向塊的I/O系統(tǒng),系統(tǒng)以塊的方式處理處理,每一個(gè)操作在一步中產(chǎn)生或者消費(fèi)一個(gè)數(shù)據(jù)庫,按塊處理要比按字節(jié)處理數(shù)據(jù)快的多。
在NIO中有幾個(gè)核心對(duì)象需要掌握:緩沖區(qū)(Buffer)、通道(Channel)、選擇器(Selector)。
4.緩沖區(qū)Buffer緩沖區(qū)實(shí)際上是一個(gè)容器對(duì)象,更直接的說,其實(shí)就是一個(gè)數(shù)組,在NIO庫中,所有數(shù)據(jù)都是用緩沖區(qū)處理的。在讀取數(shù)據(jù)時(shí),它是直接讀到緩沖區(qū)中的; 在寫入數(shù)據(jù)時(shí),它也是寫入到緩沖區(qū)中的;任何時(shí)候訪問 NIO 中的數(shù)據(jù),都是將它放到緩沖區(qū)中。而在面向流I/O系統(tǒng)中,所有數(shù)據(jù)都是直接寫入或者直接將數(shù)據(jù)讀取到Stream對(duì)象中。
在NIO中,所有的緩沖區(qū)類型都繼承于抽象類Buffer,最常用的就是ByteBuffer,對(duì)于Java中的基本類型,基本都有一個(gè)具體Buffer類型與之相對(duì)應(yīng),它們之間的繼承關(guān)系如下圖所示:
1)其中的四個(gè)屬性的含義分別如下:
容量(Capacity):緩沖區(qū)能夠容納的數(shù)據(jù)元素的最大數(shù)量。這一個(gè)容量在緩沖區(qū)創(chuàng)建時(shí)被設(shè)定,并且永遠(yuǎn)不能改變。
上界(Limit):緩沖區(qū)的第一個(gè)不能被讀或?qū)懙脑??;蛘哒f,緩沖區(qū)中現(xiàn)存元素的計(jì)數(shù)。
位置(Position):下一個(gè)要被讀或?qū)懙脑氐乃饕N恢脮?huì)自動(dòng)由相應(yīng)的 get( )和 put( )函數(shù)更新。
標(biāo)記(Mark):下一個(gè)要被讀或?qū)懙脑氐乃饕?。位置?huì)自動(dòng)由相應(yīng)的 get( )和 put( )函數(shù)更新。
2)Buffer的常見方法如下所示:
flip(): 寫模式轉(zhuǎn)換成讀模式
rewind():將 position 重置為 0 ,一般用于重復(fù)讀。
clear() :
compact(): 將未讀取的數(shù)據(jù)拷貝到 buffer 的頭部位。
mark(): reset():mark 可以標(biāo)記一個(gè)位置, reset 可以重置到該位置。
Buffer 常見類型: ByteBuffer 、 MappedByteBuffer 、 CharBuffer 、 DoubleBuffer 、 FloatBuffer 、 IntBuffer 、 LongBuffer 、 ShortBuffer 。
3)基本操作
Buffer基礎(chǔ)操作: 鏈接
緩沖區(qū)分片,緩沖區(qū)分配,直接緩存區(qū),緩存區(qū)映射,緩存區(qū)只讀:鏈接
4)緩沖區(qū)存取數(shù)據(jù)流程
存數(shù)據(jù)時(shí)position會(huì)++,當(dāng)停止數(shù)據(jù)讀取的時(shí)候
調(diào)用flip(),此時(shí)limit=position,position=0
讀取數(shù)據(jù)時(shí)position++,一直讀取到limit
clear() 清空 buffer ,準(zhǔn)備再次被寫入 (position 變成 0 , limit 變成 capacity) 。
5.通道Channel通道是一個(gè)對(duì)象,通過它可以讀取和寫入數(shù)據(jù),當(dāng)然了所有數(shù)據(jù)都通過Buffer對(duì)象來處理。我們永遠(yuǎn)不會(huì)將字節(jié)直接寫入通道中,相反是將數(shù)據(jù)寫入包含一個(gè)或者多個(gè)字節(jié)的緩沖區(qū)。同樣不會(huì)直接從通道中讀取字節(jié),而是將數(shù)據(jù)從通道讀入緩沖區(qū),再從緩沖區(qū)獲取這個(gè)字節(jié)。
在NIO中,提供了多種通道對(duì)象,而所有的通道對(duì)象都實(shí)現(xiàn)了Channel接口。它們之間的繼承關(guān)系如下圖所示:
1)使用NIO讀取數(shù)據(jù)
在前面我們說過,任何時(shí)候讀取數(shù)據(jù),都不是直接從通道讀取,而是從通道讀取到緩沖區(qū)。所以使用NIO讀取數(shù)據(jù)可以分為下面三個(gè)步驟:
從FileInputStream獲取Channel
創(chuàng)建Buffer
將數(shù)據(jù)從Channel讀取到Buffer中
2)使用NIO寫入數(shù)據(jù)
使用NIO寫入數(shù)據(jù)與讀取數(shù)據(jù)的過程類似,同樣數(shù)據(jù)不是直接寫入通道,而是寫入緩沖區(qū),可以分為下面三個(gè)步驟:
從FileInputStream獲取Channel
創(chuàng)建Buffer
將數(shù)據(jù)從Channel寫入到Buffer中
6.反應(yīng)堆1)阻塞IO模型
在老的IO包中,serverSocket和socket都是阻塞式的,因此一旦有大規(guī)模的并發(fā)行為,而每一個(gè)訪問都會(huì)開啟一個(gè)新線程。這時(shí)會(huì)有大規(guī)模的線程上下文切換操作(因?yàn)槎荚诘却?,所以資源全都被已有的線程吃掉了),這時(shí)無論是等待的線程還是正在處理的線程,響應(yīng)率都會(huì)下降,并且會(huì)影響新的線程。
2)NIO
Java NIO是在jdk1.4開始使用的,它既可以說成“新IO”,也可以說成非阻塞式I/O。下面是java NIO的工作原理:
1.由一個(gè)專門的線程來處理所有的IO事件,并負(fù)責(zé)分發(fā)。
2.事件驅(qū)動(dòng)機(jī)制:事件到的時(shí)候觸發(fā),而不是同步的去監(jiān)視事件。
3.線程通訊:線程之間通過wait,notify等方式通訊。保證每次上下文切換都是有意義的。減少無謂的線程切換。
注:每個(gè)線程的處理流程大概都是讀取數(shù)據(jù),解碼,計(jì)算處理,編碼,發(fā)送響應(yīng)。
7.選擇器傳統(tǒng)的 server / client 模式會(huì)基于 TPR ( Thread per Request ) .服務(wù)器會(huì)為每個(gè)客戶端請(qǐng)求建立一個(gè)線程.由該線程多帶帶負(fù)貴處理一個(gè)客戶請(qǐng)求。這種模式帶未的一個(gè)問題就是線程數(shù)是的劇增.大量的線程會(huì)增大服務(wù)器的開銷,大多數(shù)的實(shí)現(xiàn)為了避免這個(gè)問題,都采用了線程池模型,并設(shè)置線程池線程的最大數(shù)量,這又帶來了新的問題,如果線程池中有 200 個(gè)線程,而有 200 個(gè)用戶都在進(jìn)行大文件下載,會(huì)導(dǎo)致第 201 個(gè)用戶的請(qǐng)求無法及時(shí)處理,即便第 201 個(gè)用戶只想請(qǐng)求一個(gè)幾 KB 大小的頁面。傳統(tǒng)的 Sorvor / Client 模式如下圍所示:
NIO 中非阻塞IO采用了基于Reactor模式的工作方式,IO調(diào)用不會(huì)被阻塞,相反是注冊(cè)感興趣的特點(diǎn)IO事件,如可讀數(shù)據(jù)到達(dá),新的套接字等等,在發(fā)生持定率件時(shí),系統(tǒng)再通知我們。 NlO中實(shí)現(xiàn)非阻塞IO的核心設(shè)計(jì)Selector,Selector就是注冊(cè)各種IO事件的地方,而且當(dāng)那些事件發(fā)生時(shí),就是這個(gè)對(duì)象告訴我們所發(fā)生的事件。
當(dāng)有讀或者寫等任何注冊(cè)的事件發(fā)生時(shí),可以從Selector中獲得相應(yīng)的SelectionKey,同時(shí)從SelectionKey中可以找到發(fā)生的事件和該事件所發(fā)生的具體的SelectableChannel,以獲得客戶端發(fā)送過來的數(shù)據(jù)。
使用NIO中非阻塞IO編寫服務(wù)器處理程序,有三個(gè)步驟
1.向Selector對(duì)象注冊(cè)感興趣的事件
2.從Selector中獲取感興趣的事件
3.根據(jù)不同事件進(jìn)行相應(yīng)的處理
8.NIO源碼分析Selector是NIO的核心
epool模型
1)Selector
Selector的open
2)ServerSocketChannel
ServerSocketChannel.open
9.AIOAsynchronous IO
異步非阻塞IO
BIO ServerSocket
NIO ServerSocketChannel
AIO AsynchronousServerSocketChannel
AIO通信
看完本文的同學(xué)都掌握了嗎,還沒掌握的同學(xué)可以收藏喲,也可以轉(zhuǎn)給其他需要的同學(xué)。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/74473.html
摘要:熟練使用等抓包工具底層大神級(jí),內(nèi)核其它素養(yǎng)處理方式除了技能,我覺得素養(yǎng)態(tài)度也可以談?wù)劙踩\(yùn)維人員的權(quán)限很大,所以一定要保證帳號(hào)私鑰的安全。應(yīng)該第一時(shí)間和開發(fā)部門確認(rèn),要求優(yōu)化代碼。進(jìn)取心不斷學(xué)習(xí)運(yùn)維的知識(shí)范圍很廣,要不斷學(xué)習(xí)。 寫代碼寫了10多年, 從小公司到大公司, 前端, 后端, 數(shù)據(jù)庫, 運(yùn)維什么都做, 最后還是專職做運(yùn)維了. 整理下運(yùn)維的一些技能, 部分是網(wǎng)上資料并整理. Li...
閱讀 1235·2021-11-23 10:04
閱讀 2478·2021-11-22 15:29
閱讀 3148·2021-11-19 09:40
閱讀 793·2021-09-22 15:26
閱讀 2195·2019-08-29 16:27
閱讀 2566·2019-08-29 16:10
閱讀 1980·2019-08-29 15:43
閱讀 3387·2019-08-29 12:43