1. 程式人生 > >Java網路程式設計和NIO詳解3:IO模型與Java網路程式設計模型

Java網路程式設計和NIO詳解3:IO模型與Java網路程式設計模型

微信公眾號【Java技術江湖】一位阿里 Java 工程師的技術小站。(關注公眾號後回覆”Java“即可領取 Java基礎、進階、專案和架構師等免費學習資料,更有資料庫、分散式、微服務等熱門技術學習視訊,內容豐富,兼顧原理和實踐,另外也將贈送作者原創的Java學習指南、Java程式設計師面試指南等乾貨資源)

基本概念說明

使用者空間與核心空間

現在作業系統都是採用虛擬儲存器,那麼對32位作業系統而言,它的定址空間(虛擬儲存空間)為4G(2的32次方)。作業系統的核心是核心,獨立於普通的應用程式,可以訪問受保護的記憶體空間,也有訪問底層硬體裝置的所有許可權。為了保證使用者程序不能直接操作核心(kernel),保證核心的安全,作業系統將虛擬空間劃分為兩部分,一部分為核心空間,一部分為使用者空間。針對linux作業系統而言,將最高的1G位元組(從虛擬地址0xC0000000到0xFFFFFFFF),供核心使用,稱為核心空間,而將較低的3G位元組(從虛擬地址0x00000000到0xBFFFFFFF),供各個程序使用,稱為使用者空間。

程序切換

為了控制程序的執行,核心必須有能力掛起正在CPU上執行的程序,並恢復以前掛起的某個程序的執行。這種行為被稱為程序切換。因此可以說,任何程序都是在作業系統核心的支援下執行的,是與核心緊密相關的。

從一個程序的執行轉到另一個程序上執行,這個過程中經過下面這些變化:

  • 儲存處理機上下文,包括程式計數器和其他暫存器。
  • 更新PCB資訊。
  • 把程序的PCB移入相應的佇列,如就緒、在某事件阻塞等佇列。 選擇另一個程序執行,並更新其PCB。
  • 更新記憶體管理的資料結構。
  • 恢復處理機上下文。

程序的阻塞

正在執行的程序,由於期待的某些事件未發生,如請求系統資源失敗、等待某種操作的完成、新資料尚未到達或無新工作做等,則由系統自動執行阻塞原語(Block),使自己由執行狀態變為阻塞狀態。可見,程序的阻塞是程序自身的一種主動行為,也因此只有處於執行態的程序(獲得CPU),才可能將其轉為阻塞狀態。當程序進入阻塞狀態,是不佔用CPU資源的。

檔案描述符

檔案描述符(File descriptor)是電腦科學中的一個術語,是一個用於表述指向檔案的引用的抽象化概念。

檔案描述符在形式上是一個非負整數。實際上,它是一個索引值,指向核心為每一個程序所維護的該程序開啟檔案的記錄表。當程式開啟一個現有檔案或者建立一個新檔案時,核心向程序返回一個檔案描述符。在程式設計中,一些涉及底層的程式編寫往往會圍繞著檔案描述符展開。但是檔案描述符這一概念往往只適用於UNIX、Linux這樣的作業系統。

快取 IO

快取 IO 又被稱作標準 IO,大多數檔案系統的預設 IO 操作都是快取 IO。在 Linux 的快取 IO 機制中,作業系統會將 IO 的資料快取在檔案系統的頁快取( page cache )中,也就是說,資料會先被拷貝到作業系統核心的緩衝區中,然後才會從作業系統核心的緩衝區拷貝到應用程式的地址空間。

快取 IO 的缺點:

資料在傳輸過程中需要在應用程式地址空間和核心進行多次資料拷貝操作,這些資料拷貝操作所帶來的 CPU 以及記憶體開銷是非常大的。

IO模型介紹

作者:cooffeelis
連結:https://www.jianshu.com/p/511b9cffbdac
來源:簡書
著作權歸作者所有。商業轉載請聯絡作者獲得授權,非商業轉載請註明出處。

常用的5種IO模型:
blocking IO
nonblocking IO
IO multiplexing
signal driven IO
asynchronous IO

再說一下IO發生時涉及的物件和步驟:

對於一個network IO (這裡我們以read舉例),它會涉及到兩個系統物件:

  • 一個是呼叫這個IO的process (or thread)
  • 一個就是系統核心(kernel)

當一個read操作發生時,它會經歷兩個階段:

  • 等待資料準備,比如accept(), recv()等待資料 (Waiting for the data to be ready)
  • 將資料從核心拷貝到程序中, 比如 accept()接受到請求,recv()接收連線傳送的資料後需要複製到核心,再從核心複製到程序使用者空間(Copying the data from the kernel to the process)

對於socket流而言,資料的流向經歷兩個階段:

  • 第一步通常涉及等待網路上的資料分組到達,然後被複制到核心的某個緩衝區。
  • 第二步把資料從核心緩衝區複製到應用程序緩衝區。

記住這兩點很重要,因為這些IO Model的區別就是在兩個階段上各有不同的情況。

阻塞 I/O(blocking IO)


在linux中,預設情況下所有的socket都是blocking,一個典型的讀操作流程大概是這樣:

阻塞IO流程

當用戶程序呼叫了recvfrom這個系統呼叫,kernel就開始了IO的第一個階段:準備資料(對於網路IO來說,很多時候資料在一開始還沒有到達。比如,還沒有收到一個完整的UDP包。這個時候kernel就要等待足夠的資料到來)。這個過程需要等待,也就是說資料被拷貝到作業系統核心的緩衝區中是需要一個過程的。而在使用者程序這邊,整個程序會被阻塞(當然,是程序自己選擇的阻塞)。當kernel一直等到資料準備好了,它就會將資料從kernel中拷貝到使用者記憶體,然後kernel返回結果,使用者程序才解除block的狀態,重新執行起來。

所以,blocking IO的特點就是在IO執行的兩個階段都被block了。

非阻塞 I/O(nonblocking IO)


linux下,可以通過設定socket使其變為non-blocking。當對一個non-blocking socket執行讀操作時,流程是這個樣子:

非阻塞 I/O 流程

當用戶程序發出read操作時,如果kernel中的資料還沒有準備好,那麼它並不會block使用者程序,而是立刻返回一個error。從使用者程序角度講 ,它發起一個read操作後,並不需要等待,而是馬上就得到了一個結果。使用者程序判斷結果是一個error時,它就知道資料還沒有準備好,於是它可以再次傳送read操作。一旦kernel中的資料準備好了,並且又再次收到了使用者程序的system call,那麼它馬上就將資料拷貝到了使用者記憶體,然後返回。

所以,nonblocking IO的特點是使用者程序需要不斷的主動詢問kernel資料好了沒有。

值得注意的是,此時的非阻塞IO只是應用到等待資料上,當真正有資料到達執行recvfrom的時候,還是同步阻塞IO來的, 從圖中的copy data from kernel to user可以看出

I/O 多路複用( IO multiplexing)


IO multiplexing就是我們說的select,poll,epoll,有些地方也稱這種IO方式為event driven IO。select/epoll的好處就在於單個process就可以同時處理多個網路連線的IO。它的基本原理就是select,poll,epoll這個function會不斷的輪詢所負責的所有socket,當某個socket有資料到達了,就通知使用者程序。

I/O 多路複用流程

這個圖和blocking IO的圖其實並沒有太大的不同,事實上,還更差一些。因為這裡需要使用兩個system call (select 和 recvfrom),而blocking IO只調用了一個system call (recvfrom)。但是,用select的優勢在於它可以同時處理多個connection。

所以,如果處理的連線數不是很高的話,使用select/epoll的web server不一定比使用multi-threading + blocking IO的web server效能更好,可能延遲還更大。select/epoll的優勢並不是對於單個連線能處理得更快,而是在於能處理更多的連線。)

IO複用的實現方式目前主要有select、poll和epoll。

select和poll的原理基本相同:

  • 註冊待偵聽的fd(這裡的fd建立時最好使用非阻塞)
  • 每次呼叫都去檢查這些fd的狀態,當有一個或者多個fd就緒的時候返回
  • 返回結果中包括已就緒和未就緒的fd

相比select,poll解決了單個程序能夠開啟的檔案描述符數量有限制這個問題:select受限於FD_SIZE的限制,如果修改則需要修改這個巨集重新編譯核心;而poll通過一個pollfd陣列向核心傳遞需要關注的事件,避開了檔案描述符數量限制。

此外,select和poll共同具有的一個很大的缺點就是包含大量fd的陣列被整體複製於使用者態和核心態地址空間之間,開銷會隨著fd數量增多而線性增大。

select和poll就類似於上面說的就餐方式。但當你每次都去詢問時,老闆會把所有你點的飯菜都輪詢一遍再告訴你情況,當大量飯菜很長時間都不能準備好的情況下是很低效的。於是,老闆有些不耐煩了,就讓廚師每做好一個菜就通知他。這樣每次你再去問的時候,他會直接把已經準備好的菜告訴你,你再去端。這就是事件驅動IO就緒通知的方式-epoll。

epoll的出現,解決了select、poll的缺點:

  • 基於事件驅動的方式,避免了每次都要把所有fd都掃描一遍。
  • epoll_wait只返回就緒的fd。
  • epoll使用nmap記憶體對映技術避免了記憶體複製的開銷。
  • epoll的fd數量上限是作業系統的最大檔案控制代碼數目,這個數目一般和記憶體有關,通常遠大於1024。

目前,epoll是Linux2.6下最高效的IO複用方式,也是Nginx、Node的IO實現方式。而在freeBSD下,kqueue是另一種類似於epoll的IO複用方式。

此外,對於IO複用還有一個水平觸發和邊緣觸發的概念:

  • 水平觸發:當就緒的fd未被使用者程序處理後,下一次查詢依舊會返回,這是select和poll的觸發方式。
  • 邊緣觸發:無論就緒的fd是否被處理,下一次不再返回。理論上效能更高,但是實現相當複雜,並且任何意外的丟失事件都會造成請求處理錯誤。epoll預設使用水平觸發,通過相應選項可以使用邊緣觸發。

點評:
I/O 多路複用的特點是通過一種機制一個程序能同時等待多個檔案描述符,而這些檔案描述符(套接字描述符)其中的任意一個進入讀就緒狀態,select()函式就可以返回。
所以, IO多路複用,本質上不會有併發的功能,因為任何時候還是隻有一個程序或執行緒進行工作,它之所以能提高效率是因為select\epoll 把進來的socket放到他們的 '監視' 列表裡面,當任何socket有可讀可寫資料立馬處理,那如果select\epoll 手裡同時檢測著很多socket, 一有動靜馬上返回給程序處理,總比一個一個socket過來,阻塞等待,處理高效率。
當然也可以多執行緒/多程序方式,一個連線過來開一個程序/執行緒處理,這樣消耗的記憶體和程序切換頁會耗掉更多的系統資源。
所以我們可以結合IO多路複用和多程序/多執行緒 來高效能併發,IO複用負責提高接受socket的通知效率,收到請求後,交給程序池/執行緒池來處理邏輯。

訊號驅動

上文的就餐方式還是需要你每次都去問一下飯菜狀況。於是,你再次不耐煩了,就跟老闆說,哪個飯菜好了就通知我一聲吧。然後就自己坐在桌子那裡幹自己的事情。更甚者,你可以把手機號留給老闆,自己出門,等飯菜好了直接發條簡訊給你。這就類似訊號驅動的IO模型。

流程如下:

  • 開啟套接字訊號驅動IO功能
  • 系統呼叫sigaction執行訊號處理函式(非阻塞,立刻返回)
  • 資料就緒,生成sigio訊號,通過訊號回撥通知應用來讀取資料。

此種io方式存在的一個很大的問題:Linux中訊號佇列是有限制的,如果超過這個數字問題就無法讀取資料。

非同步非阻塞

非同步 I/O(asynchronous IO)


linux下的asynchronous IO其實用得很少。先看一下它的流程:

非同步IO 流程

使用者程序發起read操作之後,立刻就可以開始去做其它的事。而另一方面,從kernel的角度,當它受到一個asynchronous read之後,首先它會立刻返回,所以不會對使用者程序產生任何block。然後,kernel會等待資料準備完成,然後將資料拷貝到使用者記憶體,當這一切都完成之後,kernel會給使用者程序傳送一個signal,告訴它read操作完成了。

阻塞IO,非阻塞IO 與 同步IO, 非同步IO的區別和聯絡

阻塞IO VS 非阻塞IO:

概念:
阻塞和非阻塞關注的是程式在等待呼叫結果(訊息,返回值)時的狀態.
阻塞呼叫是指呼叫結果返回之前,當前執行緒會被掛起。呼叫執行緒只有在得到結果之後才會返回。非阻塞呼叫指在不能立刻得到結果之前,該呼叫不會阻塞當前執行緒。

例子:你打電話問書店老闆有沒有《分散式系統》這本書,你如果是阻塞式呼叫,你會一直把自己“掛起”,直到得到這本書有沒有的結果,如果是非阻塞式呼叫,你不管老闆有沒有告訴你,你自己先一邊去玩了, 當然你也要偶爾過幾分鐘check一下老闆有沒有返回結果。在這裡阻塞與非阻塞與是否同步非同步無關。跟老闆通過什麼方式回答你結果無關。


分析:
阻塞IO會一直block住對應的程序直到操作完成,而非阻塞IO在kernel還準備資料的情況下會立刻返回。

同步IO VS 非同步IO:

概念:
同步與非同步同步和非同步關注的是_訊息通訊機制 _(synchronous communication/ asynchronous communication)所謂同步,就是在發出一個_呼叫_時,在沒有得到結果之前,該_呼叫_就不返回。但是一旦呼叫返回,就得到返回值了。換句話說,就是由_呼叫者_主動等待這個_呼叫_的結果。而非同步則是相反,_呼叫_在發出之後,這個呼叫就直接返回了,所以沒有返回結果。換句話說,當一個非同步過程呼叫發出後,呼叫者不會立刻得到結果。而是在_呼叫_發出後,_被呼叫者_通過狀態、通知來通知呼叫者,或通過回撥函式處理這個呼叫。

典型的非同步程式設計模型比如Node.js舉個通俗的例子:你打電話問書店老闆有沒有《分散式系統》這本書,如果是同步通訊機制,書店老闆會說,你稍等,”我查一下",然後開始查啊查,等查好了(可能是5秒,也可能是一天)告訴你結果(返回結果)。而非同步通訊機制,書店老闆直接告訴你我查一下啊,查好了打電話給你,然後直接掛電話了(不返回結果)。然後查好了,他會主動打電話給你。在這裡老闆通過“回電”這種方式來回調。


分析:
在說明同步IO和非同步IO的區別之前,需要先給出兩者的定義。Stevens給出的定義(其實是POSIX的定義)是這樣子的:

A synchronous I/O operation causes the requesting process to be blocked until that I/O operation completes;
An asynchronous I/O operation does not cause the requesting process to be blocked;

兩者的區別就在於同步IO做”IO operation”的時候會將process阻塞。按照這個定義,之前所述的阻塞IO,非阻塞IO ,IO複用都屬於同步IO。
有人可能會說,非阻塞IO 並沒有被block啊。這裡有個非常“狡猾”的地方,定義中所指的”IO operation”是指真實的IO操作,就是例子中的recvfrom這個system call。非阻塞IO在執行recvfrom這個system call的時候,如果kernel的資料沒有準備好,這時候不會block程序。但是,當kernel中資料準備好的時候,recvfrom會將資料從kernel拷貝到使用者記憶體中,這個時候程序是被block了,在這段時間內,程序是被block的。

而非同步IO則不一樣,當程序發起IO 操作之後,就直接返回再也不理睬了,直到kernel傳送一個訊號,告訴程序說IO完成。在這整個過程中,程序完全沒有被block。

IO模型的形象舉例

最後,再舉幾個不是很恰當的例子來說明這四個IO Model:
有A,B,C,D四個人在釣魚:
A用的是最老式的魚竿,所以呢,得一直守著,等到魚上鉤了再拉桿;
B的魚竿有個功能,能夠顯示是否有魚上鉤,所以呢,B就和旁邊的MM聊天,隔會再看看有沒有魚上鉤,有的話就迅速拉桿;
C用的魚竿和B差不多,但他想了一個好辦法,就是同時放好幾根魚竿,然後守在旁邊,一旦有顯示說魚上鉤了,它就將對應的魚竿拉起來;
D是個有錢人,乾脆僱了一個人幫他釣魚,一旦那個人把魚釣上來了,就給D發個簡訊。

Select/Poll/Epoll 輪詢機制

select,poll,epoll本質上都是同步I/O,因為他們都需要在讀寫事件就緒後自己負責進行讀寫,也就是說這個讀寫過程是阻塞的
Select/Poll/Epoll 都是IO複用的實現方式, 上面說了使用IO複用,會把socket設定成non-blocking,然後放進Select/Poll/Epoll 各自的監視列表裡面,那麼,他們的對socket是否有資料到達的監視機制分別是怎樣的?效率又如何?我們應該使用哪種方式實現IO複用比較好?下面列出他們各自的實現方式,效率,優缺點:

(1)select,poll實現需要自己不斷輪詢所有fd集合,直到裝置就緒,期間可能要睡眠和喚醒多次交替。而epoll其實也需要呼叫epoll_wait不斷輪詢就緒連結串列,期間也可能多次睡眠和喚醒交替,但是它是裝置就緒時,呼叫回撥函式,把就緒fd放入就緒連結串列中,並喚醒在epoll_wait中進入睡眠的程序。雖然都要睡眠和交替,但是select和poll在“醒著”的時候要遍歷整個fd集合,而epoll在“醒著”的時候只要判斷一下就緒連結串列是否為空就行了,這節省了大量的CPU時間。這就是回撥機制帶來的效能提升。

(2)select,poll每次呼叫都要把fd集合從使用者態往核心態拷貝一次,並且要把current往裝置等待佇列中掛一次,而epoll只要一次拷貝,而且把current往等待佇列上掛也只掛一次(在epoll_wait的開始,注意這裡的等待佇列並不是裝置等待佇列,只是一個epoll內部定義的等待佇列)。這也能節省不少的開銷。

Java網路程式設計模型

上文講述了UNIX環境的五種IO模型。基於這五種模型,在Java中,隨著NIO和NIO2.0(AIO)的引入,一般具有以下幾種網路程式設計模型:

  • BIO
  • NIO
  • AIO

BIO

BIO是一個典型的網路程式設計模型,是通常我們實現一個服務端程式的過程,步驟如下:

  • 主執行緒accept請求阻塞
  • 請求到達,建立新的執行緒來處理這個套接字,完成對客戶端的響應。
  • 主執行緒繼續accept下一個請求

這種模型有一個很大的問題是:當客戶端連線增多時,服務端建立的執行緒也會暴漲,系統性能會急劇下降。因此,在此模型的基礎上,類似於 tomcat的bio connector,採用的是執行緒池來避免對於每一個客戶端都建立一個執行緒。有些地方把這種方式叫做偽非同步IO(把請求拋到執行緒池中非同步等待處理)。

NIO

JDK1.4開始引入了NIO類庫,這裡的NIO指的是New IO,主要是使用Selector多路複用器來實現。Selector在Linux等主流作業系統上是通過epoll實現的。

NIO的實現流程,類似於select:

  • 建立ServerSocketChannel監聽客戶端連線並繫結監聽埠,設定為非阻塞模式。
  • 建立Reactor執行緒,建立多路複用器(Selector)並啟動執行緒。
  • 將ServerSocketChannel註冊到Reactor執行緒的Selector上。監聽accept事件。
  • Selector線上程run方法中無線迴圈輪詢準備就緒的Key。
  • Selector監聽到新的客戶端接入,處理新的請求,完成tcp三次握手,建立物理連線。
  • 將新的客戶端連線註冊到Selector上,監聽讀操作。讀取客戶端傳送的網路訊息。
  • 客戶端傳送的資料就緒則讀取客戶端請求,進行處理。

相比BIO,NIO的程式設計非常複雜。

AIO

JDK1.7引入NIO2.0,提供了非同步檔案通道和非同步套接字通道的實現。其底層在windows上是通過IOCP,在Linux上是通過epoll來實現的(LinuxAsynchronousChannelProvider.java,UnixAsynchronousServerSocketChannelImpl.java)。

  • 建立AsynchronousServerSocketChannel,繫結監聽埠
  • 呼叫AsynchronousServerSocketChannel的accpet方法,傳入自己實現的CompletionHandler。包括上一步,都是非阻塞的
  • 連線傳入,回撥CompletionHandler的completed方法,在裡面,呼叫AsynchronousSocketChannel的read方法,傳入負責處理資料的CompletionHandler。
  • 資料就緒,觸發負責處理資料的CompletionHandler的completed方法。繼續做下一步處理即可。
  • 寫入操作類似,也需要傳入CompletionHandler。

其程式設計模型相比NIO有了不少的簡化。

對比

. 同步阻塞IO 偽非同步IO NIO AIO
客戶端數目 :IO執行緒 1 : 1 m : n m : 1 m : 0
IO模型 同步阻塞IO 同步阻塞IO 同步非阻塞IO 非同步非阻塞IO
吞吐量
程式設計複雜度 簡單 簡單 非常複雜 複雜

微信公眾號【黃小斜】作者是螞蟻金服 JAVA 工程師,目前在螞蟻財富負責後端開發工作,專注於 JAVA 後端技術棧,同時也懂點投資理財,堅持學習和寫作,用大廠程式設計師的視角解讀技術與網際網路,我的世界裡不只有 coding!關注公眾號後回覆”架構師“即可領取 Java基礎、進階、專案和架構師等免費學習資料,更有資料庫、分散式、微服務等熱門技術學習視訊,內容豐富,兼顧原理和實踐,另外也將贈送作者原創的Java學習指南、Java程式設計師面試指南等乾貨資源

相關推薦

Java網路程式設計NIO3IO模型Java網路程式設計模型

微信公眾號【Java技術江湖】一位阿里 Java 工程師的技術小站。(關注公眾號後回覆”Java“即可領取 Java基礎、進階、專案和架構師等免費學習資料,更有資料庫、分散式、微服務等熱門技術學習視訊,內容豐富,兼顧原理和實踐,另外也將贈送作者原創的Java學習指南、Java程式設計師面試指南等乾貨資源)

Java網絡編程NIO3IO模型Java網絡編程模型

用戶 分組 重新 spa 編譯 linux操作 計算 再次 簡化 Java網絡編程和NIO詳解3:IO模型與Java網絡編程模型 基本概念說明 用戶空間與內核空間 現在操作系統都是采用虛擬存儲器,那麽對32位操作系統而言,它的尋址空間(虛擬存儲空間)為4G(2的32次方)。

Java網路程式設計NIO開篇Java網路程式設計基礎

老曹眼中的網路程式設計基礎 轉自:https://mp.weixin.qq.com/s/XXMz5uAFSsPdg38bth2jAA 我們是幸運的,因為我們擁有網路。網路是一個神奇的東西,它改變了你和我的生活方式,改變了整個世界。 然而,網路的無標度和

Java網絡編程NIO1JAVA 中原生的 socket 通信機制

圖片 構建 -i tst 所有 ice arr 10個 屬於 Java網絡編程和NIO詳解1:JAVA 中原生的 socket 通信機制 JAVA 中原生的 socket 通信機制 摘要:本文屬於原創,歡迎轉載,轉載請保留出處:https://github.com/jas

Java網絡編程NIO5Java 非阻塞 IO 異步 IO

後來 即使 你會 fault 當我 mina 負責 second cti Java網絡編程和NIO詳解5:Java 非阻塞 IO 和異步 IO Java 非阻塞 IO 和異步 IO 轉自https://www.javadoop.com/post/nio-and-aio 本系

Java網絡編程NIO開篇Java網絡編程基礎

tcp協議 ack focus 特殊字符 設計模式 ssm 域名 代碼片段 mime Java網絡編程和NIO詳解開篇:Java網絡編程基礎 計算機網絡編程基礎 轉自:https://mp.weixin.qq.com/s/XXMz5uAFSsPdg38bth2jAA 我們是

Java網絡編程NIO8淺析mmapDirect Buffer

temp 行動 訪問 objects swa oca 空閑 long 內存操作 Java網絡編程與NIO詳解8:淺析mmap和Direct Buffer 本系列文章首發於我的個人博客:https://h2pl.github.io/ 歡迎閱覽我的CSDN專欄:Java網絡編程

Java網絡編程NIO7淺談 Linux 中NIO Selector 的實現原理

fdt 重要 文件描述 block tor create size 註冊 comm Java網絡編程和NIO詳解7:淺談 Linux 中NIO Selector 的實現原理 轉自:https://www.jianshu.com/p/2b71ea919d49 本系列文章首發於

Java網路程式設計NIO4淺析NIO包中的Buffer、Channel Selector

Java NIO:Buffer、Channel 和 Selector轉自https://www.javadoop.com/post/nio-and-aio本文將介紹 Java NIO 中三大元件 Buffer、Channel、Selector 的使用。本來要一起介紹非阻塞 I

Java網路程式設計NIO8淺析mmapDirect Buffer

微信公眾號【黃小斜】作者是螞蟻金服 JAVA 工程師,目前在螞蟻財富負責後端開發工作,專注於 JAVA 後端技術棧,同時也懂點投資理財,堅持學習和寫作,用大廠程式設計師的視角解讀技術與網際網路,我的世界裡不只有 coding!關注公眾號後回覆”架構師“即可領取 Java基礎、進階、專案和架構師等免費學習資

Java網路程式設計NIO2JAVA NIO 一步步構建I/O多路複用的請求模型

微信公眾號【黃小斜】作者是螞蟻金服 JAVA 工程師,專注於 JAVA 後端技術棧:SpringBoot、SSM全家桶、MySQL、分散式、中介軟體、微服務,同時也懂點投資理財,堅持學習和寫作,相信終身學習的力量!關注公眾號後回覆”架構師“即可領取 Java基礎、進階、專案和架構師等免費學習資料,更有資料

java的UDPTCP北京-賽車平臺出租源碼分析

ati 消息 byte ide 一段 pack catch 打包 println 1、需求分析北京-賽車平臺出租Q1446595067 最近在和硬件做網口的傳輸協議,一開始告訴我說用TCP的socket進行傳輸,我說沒問題,就寫了個socket的發送和接收方法。but過了沒

java中BiFunctionFunction

關於Lambda詳見lambda描述。關於函式式介面詳見函式式介面 首先我們來看一下BiFunction類,程式碼如下: package java.util.function; import java.util.Objects; /**  * Represents a fu

Java中ComparableComparator

該文基於JDK1.8。 一、Comparable<T> Comparable<T>原始碼如下: package java.lang; import java.util.*; /** * This interface imposes a total orde

JAVA中ListIteratorIterator辨析

    在使用java集合的時候,都需要使用Iterator。但是java集合中還有一個迭代器ListIterator,在使用List、ArrayList、LinkedList和Vector的時候可以使用。這兩種迭代器有什麼區別呢?下面我們詳細分析。這裡有一點需要明確的時候

第一次面試(java 中equal==的

        今天去了方正國際軟體有限公司面試,第一次面試,面試之後的唯一想做的就是把基礎打好。來看看筆試的第一題 Long a1=128L; Long a2=128L; Long a3=127L; Long a4=127L; Sy

java拆箱裝箱(轉)

需要注意的是:當 "=="運算子的兩個運算元都是 包裝器型別的引用,則是比較指向的是否是同一個物件,而如果其中有一個運算元是表示式(即包含算術運算)則比較的是數值(即會觸發自動拆箱的過程)。另外,對於包裝器型別,equals方法並不會進行型別轉換。   自動裝箱和拆箱問題是Java

Java集合3Iterator,fail-fast機制比較器

而不是 維護 統一 做了 count end 代碼 continue 來替 Java集合詳解3:Iterator,fail-fast機制與比較器 今天我們來探索一下LIterator,fail-fast機制與比較器的源碼。 具體代碼在我的GitHub中可以找到 https:

Spark常用運算元彙總 實戰案例、Java版本、Scala版本

官網API地址: JavaRDD:http://spark.apache.org/docs/latest/api/scala/index.html#org.apache.spark.api.java.JavaRDD  JavaPairRDD:http://spark.apache.or

java io序列化反序列化(物件流)

1、什麼是序列化與反序列化?   序列化:指把堆記憶體中的 Java 物件資料,通過某種方式把物件儲存到磁碟檔案中或者傳遞給其他網路節點(在網路上傳輸)。這個過程稱為序列化。通俗來說就是將資料結構或物件轉換成二進位制串的過程   反序列化:把磁碟檔案中的物件資料或者把網路節點上的物件資料,恢