日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > java >内容正文

java

Java NIO原理 图文分析及代码实现

發(fā)布時(shí)間:2025/6/15 java 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java NIO原理 图文分析及代码实现 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

最近在分析hadoop的RPC(Remote Procedure Call Protocol ,遠(yuǎn)程過(guò)程調(diào)用協(xié)議,它是一種通過(guò)網(wǎng)絡(luò)從遠(yuǎn)程計(jì)算機(jī)程序上請(qǐng)求服務(wù),而不需要了解底層網(wǎng)絡(luò)技術(shù)的協(xié)議。可以參考:http://baike.baidu.com/view/32726.htm?)機(jī)制時(shí),發(fā)現(xiàn)hadoop的RPC機(jī)制的實(shí)現(xiàn)主要用到了兩個(gè)技術(shù):動(dòng)態(tài)代理(動(dòng)態(tài)代理可以參考博客:http://weixiaolu.iteye.com/blog/1477774?)和java NIO。為了能夠正確地分析hadoop的RPC源碼,我覺(jué)得很有必要先研究一下java NIO的原理和具體實(shí)現(xiàn)。

這篇博客我主要從兩個(gè)方向來(lái)分析java NIO

目錄:
一.java NIO 和阻塞I/O的區(qū)別
???? 1. 阻塞I/O通信模型
???? 2. java NIO原理及通信模型
二.java NIO服務(wù)端和客戶端代碼實(shí)現(xiàn)
?

具體分析:?

一.java NIO 和阻塞I/O的區(qū)別?

1. 阻塞I/O通信模型
?

假如現(xiàn)在你對(duì)阻塞I/O已有了一定了解,我們知道阻塞I/O在調(diào)用InputStream.read()方法時(shí)是阻塞的,它會(huì)一直等到數(shù)據(jù)到來(lái)時(shí)(或超時(shí))才會(huì)返回;同樣,在調(diào)用ServerSocket.accept()方法時(shí),也會(huì)一直阻塞到有客戶端連接才會(huì)返回,每個(gè)客戶端連接過(guò)來(lái)后,服務(wù)端都會(huì)啟動(dòng)一個(gè)線程去處理該客戶端的請(qǐng)求。阻塞I/O的通信模型示意圖如下:

?

?

如果你細(xì)細(xì)分析,一定會(huì)發(fā)現(xiàn)阻塞I/O存在一些缺點(diǎn)。根據(jù)阻塞I/O通信模型,我總結(jié)了它的兩點(diǎn)缺點(diǎn):
1. 當(dāng)客戶端多時(shí),會(huì)創(chuàng)建大量的處理線程。且每個(gè)線程都要占用棧空間和一些CPU時(shí)間

2. 阻塞可能帶來(lái)頻繁的上下文切換,且大部分上下文切換可能是無(wú)意義的。

在這種情況下非阻塞式I/O就有了它的應(yīng)用前景。

2.?
java NIO原理及通信模型?

Java NIO是在jdk1.4開(kāi)始使用的,它既可以說(shuō)成“新I/O”,也可以說(shuō)成非阻塞式I/O。下面是java NIO的工作原理:

1. 由一個(gè)專門的線程來(lái)處理所有的 IO 事件,并負(fù)責(zé)分發(fā)。?
2. 事件驅(qū)動(dòng)機(jī)制:事件到的時(shí)候觸發(fā),而不是同步的去監(jiān)視事件。?
3. 線程通訊:線程之間通過(guò) wait,notify 等方式通訊。保證每次上下文切換都是有意義的。減少無(wú)謂的線程切換。?

閱讀過(guò)一些資料之后,下面貼出我理解的java NIO的工作原理圖:

?

?

(注:每個(gè)線程的處理流程大概都是讀取數(shù)據(jù)、解碼、計(jì)算處理、編碼、發(fā)送響應(yīng)。)

Java NIO的服務(wù)端只需啟動(dòng)一個(gè)專門的線程來(lái)處理所有的 IO 事件,這種通信模型是怎么實(shí)現(xiàn)的呢?呵呵,我們一起來(lái)探究它的奧秘吧。java NIO采用了雙向通道(channel)進(jìn)行數(shù)據(jù)傳輸,而不是單向的流(stream),在通道上可以注冊(cè)我們感興趣的事件。一共有以下四種事件:

?

事件名對(duì)應(yīng)值
服務(wù)端接收客戶端連接事件SelectionKey.OP_ACCEPT(16)
客戶端連接服務(wù)端事件SelectionKey.OP_CONNECT(8)
讀事件SelectionKey.OP_READ(1)
寫事件SelectionKey.OP_WRITE(4)

?

??
??
??
??
??

服務(wù)端和客戶端各自維護(hù)一個(gè)管理通道的對(duì)象,我們稱之為selector,該對(duì)象能檢測(cè)一個(gè)或多個(gè)通道 (channel) 上的事件。我們以服務(wù)端為例,如果服務(wù)端的selector上注冊(cè)了讀事件,某時(shí)刻客戶端給服務(wù)端發(fā)送了一些數(shù)據(jù),阻塞I/O這時(shí)會(huì)調(diào)用read()方法阻塞地讀取數(shù)據(jù),而NIO的服務(wù)端會(huì)在selector中添加一個(gè)讀事件。服務(wù)端的處理線程會(huì)輪詢地訪問(wèn)selector,如果訪問(wèn)selector時(shí)發(fā)現(xiàn)有感興趣的事件到達(dá),則處理這些事件,如果沒(méi)有感興趣的事件到達(dá),則處理線程會(huì)一直阻塞直到感興趣的事件到達(dá)為止。下面是我理解的java NIO的通信模型示意圖:

?

?

二.java NIO服務(wù)端和客戶端代碼實(shí)現(xiàn)?

為了更好地理解java NIO,下面貼出服務(wù)端和客戶端的簡(jiǎn)單代碼實(shí)現(xiàn)。

服務(wù)端:

?

Java代碼??
  • package?cn.nio;??
  • ??
  • import?java.io.IOException;??
  • import?java.net.InetSocketAddress;??
  • import?java.nio.ByteBuffer;??
  • import?java.nio.channels.SelectionKey;??
  • import?java.nio.channels.Selector;??
  • import?java.nio.channels.ServerSocketChannel;??
  • import?java.nio.channels.SocketChannel;??
  • import?java.util.Iterator;??
  • ??
  • /**?
  • ?*?NIO服務(wù)端?
  • ?*?@author?小路?
  • ?*/??
  • public?class?NIOServer?{??
  • ????//通道管理器??
  • ????private?Selector?selector;??
  • ??
  • ????/**?
  • ?????*?獲得一個(gè)ServerSocket通道,并對(duì)該通道做一些初始化的工作?
  • ?????*?@param?port??綁定的端口號(hào)?
  • ?????*?@throws?IOException?
  • ?????*/??
  • ????public?void?initServer(int?port)?throws?IOException?{??
  • ????????//?獲得一個(gè)ServerSocket通道??
  • ????????ServerSocketChannel?serverChannel?=?ServerSocketChannel.open();??
  • ????????//?設(shè)置通道為非阻塞??
  • ????????serverChannel.configureBlocking(false);??
  • ????????//?將該通道對(duì)應(yīng)的ServerSocket綁定到port端口??
  • ????????serverChannel.socket().bind(new?InetSocketAddress(port));??
  • ????????//?獲得一個(gè)通道管理器??
  • ????????this.selector?=?Selector.open();??
  • ????????//將通道管理器和該通道綁定,并為該通道注冊(cè)SelectionKey.OP_ACCEPT事件,注冊(cè)該事件后,??
  • ????????//當(dāng)該事件到達(dá)時(shí),selector.select()會(huì)返回,如果該事件沒(méi)到達(dá)selector.select()會(huì)一直阻塞。??
  • ????????serverChannel.register(selector,?SelectionKey.OP_ACCEPT);??
  • ????}??
  • ??
  • ????/**?
  • ?????*?采用輪詢的方式監(jiān)聽(tīng)selector上是否有需要處理的事件,如果有,則進(jìn)行處理?
  • ?????*?@throws?IOException?
  • ?????*/??
  • ????@SuppressWarnings("unchecked")??
  • ????public?void?listen()?throws?IOException?{??
  • ????????System.out.println("服務(wù)端啟動(dòng)成功!");??
  • ????????//?輪詢?cè)L問(wèn)selector??
  • ????????while?(true)?{??
  • ????????????//當(dāng)注冊(cè)的事件到達(dá)時(shí),方法返回;否則,該方法會(huì)一直阻塞??
  • ????????????selector.select();??
  • ????????????//?獲得selector中選中的項(xiàng)的迭代器,選中的項(xiàng)為注冊(cè)的事件??
  • ????????????Iterator?ite?=?this.selector.selectedKeys().iterator();??
  • ????????????while?(ite.hasNext())?{??
  • ????????????????SelectionKey?key?=?(SelectionKey)?ite.next();??
  • ????????????????//?刪除已選的key,以防重復(fù)處理??
  • ????????????????ite.remove();??
  • ????????????????//?客戶端請(qǐng)求連接事件??
  • ????????????????if?(key.isAcceptable())?{??
  • ????????????????????ServerSocketChannel?server?=?(ServerSocketChannel)?key??
  • ????????????????????????????.channel();??
  • ????????????????????//?獲得和客戶端連接的通道??
  • ????????????????????SocketChannel?channel?=?server.accept();??
  • ????????????????????//?設(shè)置成非阻塞??
  • ????????????????????channel.configureBlocking(false);??
  • ??
  • ????????????????????//在這里可以給客戶端發(fā)送信息哦??
  • ????????????????????channel.write(ByteBuffer.wrap(new?String("向客戶端發(fā)送了一條信息").getBytes()));??
  • ????????????????????//在和客戶端連接成功之后,為了可以接收到客戶端的信息,需要給通道設(shè)置讀的權(quán)限。??
  • ????????????????????channel.register(this.selector,?SelectionKey.OP_READ);??
  • ??????????????????????
  • ????????????????????//?獲得了可讀的事件??
  • ????????????????}?else?if?(key.isReadable())?{??
  • ????????????????????????read(key);??
  • ????????????????}??
  • ??
  • ????????????}??
  • ??
  • ????????}??
  • ????}??
  • ????/**?
  • ?????*?處理讀取客戶端發(fā)來(lái)的信息?的事件?
  • ?????*?@param?key?
  • ?????*?@throws?IOException??
  • ?????*/??
  • ????public?void?read(SelectionKey?key)?throws?IOException{??
  • ????????//?服務(wù)器可讀取消息:得到事件發(fā)生的Socket通道??
  • ????????SocketChannel?channel?=?(SocketChannel)?key.channel();??
  • ????????//?創(chuàng)建讀取的緩沖區(qū)??
  • ????????ByteBuffer?buffer?=?ByteBuffer.allocate(10);??
  • ????????channel.read(buffer);??
  • ????????byte[]?data?=?buffer.array();??
  • ????????String?msg?=?new?String(data).trim();??
  • ????????System.out.println("服務(wù)端收到信息:"+msg);??
  • ????????ByteBuffer?outBuffer?=?ByteBuffer.wrap(msg.getBytes());??
  • ????????channel.write(outBuffer);//?將消息回送給客戶端??
  • ????}??
  • ??????
  • ????/**?
  • ?????*?啟動(dòng)服務(wù)端測(cè)試?
  • ?????*?@throws?IOException??
  • ?????*/??
  • ????public?static?void?main(String[]?args)?throws?IOException?{??
  • ????????NIOServer?server?=?new?NIOServer();??
  • ????????server.initServer(8000);??
  • ????????server.listen();??
  • ????}??
  • ??
  • }??
  • ?

    ?

    客戶端:

    ?

    ?

    Java代碼??
  • package?cn.nio;??
  • ??
  • import?java.io.IOException;??
  • import?java.net.InetSocketAddress;??
  • import?java.nio.ByteBuffer;??
  • import?java.nio.channels.SelectionKey;??
  • import?java.nio.channels.Selector;??
  • import?java.nio.channels.SocketChannel;??
  • import?java.util.Iterator;??
  • ??
  • /**?
  • ?*?NIO客戶端?
  • ?*?@author?小路?
  • ?*/??
  • public?class?NIOClient?{??
  • ????//通道管理器??
  • ????private?Selector?selector;??
  • ??
  • ????/**?
  • ?????*?獲得一個(gè)Socket通道,并對(duì)該通道做一些初始化的工作?
  • ?????*?@param?ip?連接的服務(wù)器的ip?
  • ?????*?@param?port??連接的服務(wù)器的端口號(hào)??????????
  • ?????*?@throws?IOException?
  • ?????*/??
  • ????public?void?initClient(String?ip,int?port)?throws?IOException?{??
  • ????????//?獲得一個(gè)Socket通道??
  • ????????SocketChannel?channel?=?SocketChannel.open();??
  • ????????//?設(shè)置通道為非阻塞??
  • ????????channel.configureBlocking(false);??
  • ????????//?獲得一個(gè)通道管理器??
  • ????????this.selector?=?Selector.open();??
  • ??????????
  • ????????//?客戶端連接服務(wù)器,其實(shí)方法執(zhí)行并沒(méi)有實(shí)現(xiàn)連接,需要在listen()方法中調(diào)??
  • ????????//用channel.finishConnect();才能完成連接??
  • ????????channel.connect(new?InetSocketAddress(ip,port));??
  • ????????//將通道管理器和該通道綁定,并為該通道注冊(cè)SelectionKey.OP_CONNECT事件。??
  • ????????channel.register(selector,?SelectionKey.OP_CONNECT);??
  • ????}??
  • ??
  • ????/**?
  • ?????*?采用輪詢的方式監(jiān)聽(tīng)selector上是否有需要處理的事件,如果有,則進(jìn)行處理?
  • ?????*?@throws?IOException?
  • ?????*/??
  • ????@SuppressWarnings("unchecked")??
  • ????public?void?listen()?throws?IOException?{??
  • ????????//?輪詢?cè)L問(wèn)selector??
  • ????????while?(true)?{??
  • ????????????selector.select();??
  • ????????????//?獲得selector中選中的項(xiàng)的迭代器??
  • ????????????Iterator?ite?=?this.selector.selectedKeys().iterator();??
  • ????????????while?(ite.hasNext())?{??
  • ????????????????SelectionKey?key?=?(SelectionKey)?ite.next();??
  • ????????????????//?刪除已選的key,以防重復(fù)處理??
  • ????????????????ite.remove();??
  • ????????????????//?連接事件發(fā)生??
  • ????????????????if?(key.isConnectable())?{??
  • ????????????????????SocketChannel?channel?=?(SocketChannel)?key??
  • ????????????????????????????.channel();??
  • ????????????????????//?如果正在連接,則完成連接??
  • ????????????????????if(channel.isConnectionPending()){??
  • ????????????????????????channel.finishConnect();??
  • ??????????????????????????
  • ????????????????????}??
  • ????????????????????//?設(shè)置成非阻塞??
  • ????????????????????channel.configureBlocking(false);??
  • ??
  • ????????????????????//在這里可以給服務(wù)端發(fā)送信息哦??
  • ????????????????????channel.write(ByteBuffer.wrap(new?String("向服務(wù)端發(fā)送了一條信息").getBytes()));??
  • ????????????????????//在和服務(wù)端連接成功之后,為了可以接收到服務(wù)端的信息,需要給通道設(shè)置讀的權(quán)限。??
  • ????????????????????channel.register(this.selector,?SelectionKey.OP_READ);??
  • ??????????????????????
  • ????????????????????//?獲得了可讀的事件??
  • ????????????????}?else?if?(key.isReadable())?{??
  • ????????????????????????read(key);??
  • ????????????????}??
  • ??
  • ????????????}??
  • ??
  • ????????}??
  • ????}??
  • ????/**?
  • ?????*?處理讀取服務(wù)端發(fā)來(lái)的信息?的事件?
  • ?????*?@param?key?
  • ?????*?@throws?IOException??
  • ?????*/??
  • ????public?void?read(SelectionKey?key)?throws?IOException{??
  • ????????//和服務(wù)端的read方法一樣??
  • ????}??
  • ??????
  • ??????
  • ????/**?
  • ?????*?啟動(dòng)客戶端測(cè)試?
  • ?????*?@throws?IOException??
  • ?????*/??
  • ????public?static?void?main(String[]?args)?throws?IOException?{??
  • ????????NIOClient?client?=?new?NIOClient();??
  • ????????client.initClient("localhost",8000);??
  • ????????client.listen();??
  • ????}??
  • ??
  • }??
  • ?

    ?

    小結(jié):?

    終于把動(dòng)態(tài)代理和java NIO分析完了,呵呵,下面就要分析hadoop的RPC機(jī)制源碼了,博客地址:http://weixiaolu.iteye.com/blog/1504898?。不過(guò)如果對(duì)java NIO的理解存在異議的,歡迎一起討論。

    總結(jié)

    以上是生活随笔為你收集整理的Java NIO原理 图文分析及代码实现的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 日韩精品视频在线免费观看 | 日本a一级 | 久久理论片 | 亚洲成人一级 | av毛片精品 | 中文字幕av久久 | jlzzjizz在线播放观看 | 九九av | 一区二区 中文字幕 | 三级色网站 | 久久精品国产亚洲av麻豆 | 久久免费少妇高潮久久精品99 | 日本久久激情 | 午夜插插插 | 日韩黄色网页 | 天天射综合网站 | 天天看a| 欧美二区在线观看 | 国产妞干网| 美女被叉叉的影院 | 美女久久久久久久 | www.一区二区三区 | 91插插插插插插插插 | 一本久道久久综合无码中文 | 四川话毛片少妇免费看 | 欧美国产第一页 | 伊人伊人| 国产性―交―乱―色―情人 | 日韩精品一区二区三区在线视频 | 天天操天天操天天操天天操 | 91人人爱 | 91手机在线观看 | 精品人妻一区二区三区久久 | 在线免费观看的av | 国产精品电影一区 | 国产性久久 | 午夜影视福利 | 成人性生活视频 | 亚洲av无码专区在线播放中文 | 欧美一级片免费在线观看 | 夜夜嗨aⅴ一区二区三区 | 韩日精品在线观看 | 亚洲一卡二卡在线 | 777777av| 亚洲综合在线成人 | 日韩在线无 | 四虎影院新网址 | 久久久一区二区 | 西欧free性满足hd老熟妇 | 青青国产精品视频 | 亚洲精品在线免费 | 葵司av电影 | 国产精品久久久久久久久久妞妞 | 亚洲a在线播放 | 九九综合九九综合 | 日韩亚洲一区二区三区 | 插插看| 一级淫片在线观看 | 亚洲精品一区中文字幕乱码 | 色综合av| av福利片 | 久久国产主播 | 美女隐私免费看 | 在线观看免费视频一区 | 一级精品视频 | 福利视频免费看 | 午夜大片 | 成人网址在线观看 | 亚洲精品 欧美 | 粉嫩aⅴ一区二区三区四区五区 | 人与拘一级a毛片 | 日韩免费在线观看 | 蜜臀av在线播放 | 97人人澡人人爽人人模亚洲 | 国产综合av | 长腿校花无力呻吟娇喘的视频 | 中文字幕乱码av | 亚洲中文字幕一区 | 久久99热这里只频精品6学生 | 精品一区二区三区精华液 | 国产精品无码久久久久一区二区 | 日本中文字幕二区 | 好大好舒服视频 | 国产精品国产三级国产专播品爱网 | 影音先锋丝袜制服 | 日本高清视频免费观看 | 少妇野外性xx老女人野外性xx | 精品乱人伦一区二区三区 | 在线观看免费黄视频 | 91精品久久人妻一区二区夜夜夜 | 中国1级毛片 | 秋霞黄色片 | 亚洲奶水xxxx哺乳期 | 欧美日韩高清一区二区 国产亚洲免费看 | 久久久亚洲精品视频 | 天天干夜夜草 | 国产视频精品视频 | 黄色一级片免费观看 | 亚洲精品久久久久中文字幕二区 |