欧美一区二区三区老妇人-欧美做爰猛烈大尺度电-99久久夜色精品国产亚洲a-亚洲福利视频一区二区

netty系列之JavaBIONIOAIO進(jìn)化史-創(chuàng)新互聯(lián)

簡(jiǎn)介

上一章我們介紹了IO的五種模型,實(shí)際上Java只支持其中的三種,即BIO/NIO/AIO。

創(chuàng)新互聯(lián)建站是一家專注于網(wǎng)站設(shè)計(jì)制作、成都網(wǎng)站制作與策劃設(shè)計(jì),古田網(wǎng)站建設(shè)哪家好?創(chuàng)新互聯(lián)建站做網(wǎng)站,專注于網(wǎng)站建設(shè)十余年,網(wǎng)設(shè)計(jì)領(lǐng)域的專業(yè)建站公司;建站業(yè)務(wù)涵蓋:古田等地區(qū)。古田做網(wǎng)站價(jià)格咨詢:18980820575

本文將介紹Java中這三種IO的進(jìn)化史,并從使用的角度剖析它們背后的故事。

Java BIO

BIO概念解析

BIO,Blocking IO,阻塞IO,它是Java的上古產(chǎn)品,自出生就有的東西(JDK 1.0)。

使用BIO則數(shù)據(jù)準(zhǔn)備和數(shù)據(jù)從內(nèi)核空間拷貝到用戶空間兩個(gè)階段都是阻塞的。

netty系列之Java BIO NIO AIO進(jìn)化史

BIO使用案例

public?class?EchoServer?{????public?static?void?main(String[]?args)?throws?IOException?{
????????ServerSocket?serverSocket?=?new?ServerSocket(8080);????????while?(true)?{
????????????System.out.println("start?accept");
????????????Socket?socket?=?serverSocket.accept();
????????????System.out.println("new?conn:?"?+?socket.getRemoteSocketAddress());????????????new?Thread(()->{????????????????try?{
????????????????????BufferedReader?reader?=?new?BufferedReader(new?InputStreamReader(socket.getInputStream()));
????????????????????String?msg;????????????????????//?讀取消息,本文來源公從號(hào)彤哥讀源碼
????????????????????while?((msg?=?reader.readLine())?!=?null)?{????????????????????????if?(msg.equalsIgnoreCase("quit"))?{
????????????????????????????reader.close();
????????????????????????????socket.close();????????????????????????????break;
????????????????????????}?else?{
????????????????????????????System.out.println("receive?msg:?"?+?msg);
????????????????????????}
????????????????????}
????????????????}?catch?(IOException?e)?{
????????????????????e.printStackTrace();
????????????????}
????????????}).start();
????????}
????}
}

客戶端可以使用telnet來測(cè)試,而且你可以使用多個(gè)telnet來測(cè)試:

[c:\~]$?telnet?127.0.0.1?8080Connecting?to?127.0.0.1:8080...
Connection?established.
To?escape?to?local?shell,?press?'Ctrl+Alt+]'.
hello?world
我是人才
quit
Connection?closed?by?foreign?host.

BIO的使用方式非常簡(jiǎn)單,服務(wù)端接收到一個(gè)連接就啟動(dòng)一個(gè)線程來處理這個(gè)連接的所有請(qǐng)求。

netty系列之Java BIO NIO AIO進(jìn)化史

所以,BIO大的缺點(diǎn)就是浪費(fèi)資源,只能處理少量的連接,線程數(shù)隨著連接數(shù)線性增加,連接越多線程越多,直到抗不住。

Java NIO

NIO概念解析

NIO,New IO,JDK1.4開始支持,內(nèi)部是基于多路復(fù)用的IO模型。

netty系列之Java BIO NIO AIO進(jìn)化史

這里有個(gè)歧義,很多人認(rèn)為Java的NIO是Non-Blocking IO的縮寫,其實(shí)并不是。

使用NIO則多條連接的數(shù)據(jù)準(zhǔn)備階段會(huì)阻塞在select上,數(shù)據(jù)從內(nèi)核空間拷貝到用戶空間依然是阻塞的。

因?yàn)榈谝浑A段并不是連接本身處于阻塞階段,所以通常來說NIO也可以看作是同步非阻塞IO。

NIO使用案例

public?class?EchoServer?{????public?static?void?main(String[]?args)?throws?IOException?{
????????Selector?selector?=?Selector.open();
????????ServerSocketChannel?serverSocketChannel?=?ServerSocketChannel.open();
????????serverSocketChannel.bind(new?InetSocketAddress(8080));
????????serverSocketChannel.configureBlocking(false);????????//?將accept事件綁定到selector上
????????serverSocketChannel.register(selector,?SelectionKey.OP_ACCEPT);????????while?(true)?{????????????//?阻塞在select上
????????????selector.select();
????????????Set<SelectionKey>?selectionKeys?=?selector.selectedKeys();????????????//?遍歷selectKeys
????????????Iterator<SelectionKey>?iterator?=?selectionKeys.iterator();????????????while?(iterator.hasNext())?{
????????????????SelectionKey?selectionKey?=?iterator.next();????????????????//?如果是accept事件
????????????????if?(selectionKey.isAcceptable())?{
????????????????????ServerSocketChannel?ssc?=?(ServerSocketChannel)?selectionKey.channel();
????????????????????SocketChannel?socketChannel?=?ssc.accept();
????????????????????System.out.println("accept?new?conn:?"?+?socketChannel.getRemoteAddress());
????????????????????socketChannel.configureBlocking(false);
????????????????????socketChannel.register(selector,?SelectionKey.OP_READ);
????????????????}?else?if?(selectionKey.isReadable())?{????????????????????//?如果是讀取事件,本文來源公從號(hào)彤哥讀源碼
????????????????????SocketChannel?socketChannel?=?(SocketChannel)?selectionKey.channel();
????????????????????ByteBuffer?buffer?=?ByteBuffer.allocate(1024);????????????????????//?將數(shù)據(jù)讀入到buffer中
????????????????????int?length?=?socketChannel.read(buffer);????????????????????if?(length?>?0)?{
????????????????????????buffer.flip();????????????????????????byte[]?bytes?=?new?byte[buffer.remaining()];????????????????????????//?將數(shù)據(jù)讀入到byte數(shù)組中
????????????????????????buffer.get(bytes);????????????????????????//?換行符會(huì)跟著消息一起傳過來
????????????????????????String?content?=?new?String(bytes,?"UTF-8").replace("\r\n",?"");????????????????????????if?(content.equalsIgnoreCase("quit"))?{
????????????????????????????selectionKey.cancel();
????????????????????????????socketChannel.close();
????????????????????????}?else?{
????????????????????????????System.out.println("receive?msg:?"?+?content);
????????????????????????}
????????????????????}
????????????????}
????????????????iterator.remove();
????????????}
????????}
????}
}

這里同樣使用telnet測(cè)試,而且你可以使用多個(gè)telnet來測(cè)試:

[c:\~]$?telnet?127.0.0.1?8080Connecting?to?127.0.0.1:8080...
Connection?established.
To?escape?to?local?shell,?press?'Ctrl+Alt+]'.
hello?world
我是人才
quit
Connection?closed?by?foreign?host.

NIO的使用方式就有點(diǎn)復(fù)雜了,但是一個(gè)線程就可以處理很多連接。

首先,需要注冊(cè)一個(gè)ServerSocketChannel并把它注冊(cè)到selector上并監(jiān)聽accept事件,然后accept到連接后會(huì)獲取到SocketChannel,同樣把SocketChannel也注冊(cè)到selector上,但是監(jiān)聽的是read事件。焦作國(guó)醫(yī)胃腸醫(yī)院靠譜嗎_正規(guī)胃腸專科醫(yī)院:http://jz.lieju.com/zhuankeyiyuan/37570896.htm

netty系列之Java BIO NIO AIO進(jìn)化史

NIO大的優(yōu)點(diǎn),就是一個(gè)線程就可以處理大量的連接,缺點(diǎn)是不適合處理阻塞性任務(wù),因?yàn)樽枞匀蝿?wù)會(huì)把這個(gè)線程占有著,其它連接的請(qǐng)求將得不到及時(shí)處理。

Java AIO

AIO概念介紹

AIO,Asynchronous IO,異步IO,JDK1.7開始支持,算是一種比較完美的IO,Windows下比較成熟,但Linux下還不太成熟。

netty系列之Java BIO NIO AIO進(jìn)化史

使用異步IO則會(huì)在請(qǐng)求時(shí)立即返回,并在數(shù)據(jù)已準(zhǔn)備且已拷貝到用戶空間后進(jìn)行回調(diào)處理,兩個(gè)階段都不會(huì)阻塞。

AIO使用案例

public?class?EchoServer?{????public?static?void?main(String[]?args)?throws?IOException?{
????????AsynchronousServerSocketChannel?serverSocketChannel?=?AsynchronousServerSocketChannel.open();
????????serverSocketChannel.bind(new?InetSocketAddress(8080));????????//?監(jiān)聽accept事件,本文來源公從號(hào)彤哥讀源碼
????????serverSocketChannel.accept(null,?new?CompletionHandler<AsynchronousSocketChannel,?Object>()?{????????????@Override
????????????public?void?completed(AsynchronousSocketChannel?socketChannel,?Object?attachment)?{????????????????try?{
????????????????????System.out.println("accept?new?conn:?"?+?socketChannel.getRemoteAddress());????????????????????//?再次監(jiān)聽accept事件
????????????????????serverSocketChannel.accept(null,?this);????????????????????//?消息的處理
????????????????????while?(true)?{
????????????????????????ByteBuffer?buffer?=?ByteBuffer.allocate(1024);????????????????????????//?將數(shù)據(jù)讀入到buffer中
????????????????????????Future<Integer>?future?=?socketChannel.read(buffer);????????????????????????if?(future.get()?>?0)?{
????????????????????????????buffer.flip();????????????????????????????byte[]?bytes?=?new?byte[buffer.remaining()];????????????????????????????//?將數(shù)據(jù)讀入到byte數(shù)組中
????????????????????????????buffer.get(bytes);

????????????????????????????String?content?=?new?String(bytes,?"UTF-8");????????????????????????????//?換行符會(huì)當(dāng)成另一條消息傳過來
????????????????????????????if?(content.equals("\r\n"))?{????????????????????????????????continue;
????????????????????????????}????????????????????????????if?(content.equalsIgnoreCase("quit"))?{
????????????????????????????????socketChannel.close();????????????????????????????????break;
????????????????????????????}?else?{
????????????????????????????????System.out.println("receive?msg:?"?+?content);
????????????????????????????}
????????????????????????}
????????????????????}
????????????????}?catch?(Exception?e)?{
????????????????????e.printStackTrace();
????????????????}
????????????}????????????@Override
????????????public?void?failed(Throwable?exc,?Object?attachment)?{
????????????????System.out.println("failed");
????????????}
????????});????????//?阻塞住主線程
????????System.in.read();
????}
}

這里同樣使用telnet測(cè)試,而且你可以使用多個(gè)telnet來測(cè)試:

[c:\~]$?telnet?127.0.0.1?8080Connecting?to?127.0.0.1:8080...
Connection?established.
To?escape?to?local?shell,?press?'Ctrl+Alt+]'.
hello?world
我是人才
quit
Connection?closed?by?foreign?host.

AIO的使用方式不算太復(fù)雜,默認(rèn)會(huì)啟一組線程來處理用戶的請(qǐng)求,而且如果在處理阻塞性任務(wù),還會(huì)自動(dòng)增加新的線程來處理其它連接的任務(wù)。

首先,創(chuàng)建一個(gè)AsynchronousServerSocketChannel并調(diào)用其accept方法,這一步相當(dāng)于監(jiān)聽了accept事件,在收到accept事件后會(huì)獲取到AsynchronousSocketChannel,然后就可以在回調(diào)方法completed()里面讀取數(shù)據(jù)了,當(dāng)然也要繼續(xù)監(jiān)聽accept事件。

AIO大的優(yōu)點(diǎn),就是少量的線程就可以處理大量的連接,而且可以處理阻塞性任務(wù),但不能大量阻塞,否則線程數(shù)量會(huì)膨脹。

槽點(diǎn)

(1)三種IO的實(shí)現(xiàn)方式中對(duì)于換行符的處理竟然都不一樣,BIO中不會(huì)把換行符帶過來(其實(shí)是帶過來了,因?yàn)橛昧藃eadLine()方法,所以換行符沒了),NIO中會(huì)把換行符加在消息末尾,AIO中會(huì)把換行符當(dāng)成一條新的消息傳過來,很神奇,為啥不統(tǒng)一處理呢,也很疑惑。焦作國(guó)醫(yī)胃腸醫(yī)院地址__大愛國(guó)醫(yī):http://jz.lieju.com/zhuankeyiyuan/37570264.htm

(2)JDK自帶的ByteBuffer是一個(gè)難用的東西。

總結(jié)

本文我們從概念和使用兩個(gè)角度分別介紹了BIO/NIO/AIO三種IO模型。

問題

看起來JDK的實(shí)現(xiàn)似乎很完美啊,為什么還會(huì)有Netty呢?

最后,也歡迎來我的公從號(hào)彤哥讀源碼系統(tǒng)地學(xué)習(xí)源碼&架構(gòu)的知識(shí)。

創(chuàng)新互聯(lián)www.cdcxhl.cn,專業(yè)提供香港、美國(guó)云服務(wù)器,動(dòng)態(tài)BGP最優(yōu)骨干路由自動(dòng)選擇,持續(xù)穩(wěn)定高效的網(wǎng)絡(luò)助力業(yè)務(wù)部署。公司持有工信部辦法的idc、isp許可證, 機(jī)房獨(dú)有T級(jí)流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確進(jìn)行流量調(diào)度,確保服務(wù)器高可用性。佳節(jié)活動(dòng)現(xiàn)已開啟,新人活動(dòng)云服務(wù)器買多久送多久。

本文標(biāo)題:netty系列之JavaBIONIOAIO進(jìn)化史-創(chuàng)新互聯(lián)
文章源于:http://chinadenli.net/article44/dhjshe.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供微信小程序定制網(wǎng)站、做網(wǎng)站、網(wǎng)站排名、電子商務(wù)、靜態(tài)網(wǎng)站

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

成都seo排名網(wǎng)站優(yōu)化