电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

您的位置:首頁技術文章
文章詳情頁

Java 中的io模型詳解

瀏覽:101日期:2022-08-14 18:54:37
1. BIO

我們先看一個 Java 例子:

package cn.bridgeli.demo; import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.net.ServerSocket;import java.net.Socket; /** * @author bridgeli */public class SocketBIO { public static void main(String[] args) throws Exception {ServerSocket server = new ServerSocket(9090, 20); System.out.println('step1: new ServerSocket(9090) '); while (true) { Socket client = server.accept(); System.out.println('step2:client: ' + client.getPort()); new Thread(new Runnable() {@Overridepublic void run() { InputStream inputStream = null; BufferedReader reader = null; try {inputStream = client.getInputStream();reader = new BufferedReader(new InputStreamReader(inputStream));while (true) { String dataLine = reader.readLine(); //阻塞2 if (null != dataLine) {System.out.println(dataLine); } else {client.close();break; }}System.out.println('客戶端斷開'); } catch (IOException e) {e.printStackTrace(); } finally {if (null != reader) { try {reader.close(); } catch (IOException e) {e.printStackTrace(); }}if (null!= inputStream) { try {inputStream.close(); } catch (IOException e) {e.printStackTrace(); }} } } }).start(); } } }

BIO 是最初始的 IO 模型,該模型有兩個大問題:1. accept 是阻塞的;2. read 也是阻塞的,也就是說我們的服務器起來之后,首先會在 accept 處阻塞,等待客戶端連接,但有一個客戶端連接的時候,我們可以從客戶端處讀取數據,這個時候也是阻塞的,所以我們的系統只能是單連接的,當有多個客戶端連接的時候,只能一個一個的排著隊連接,然后從客戶端中讀取數據,為了實現多連接,這就要求我們必須啟用線程來解決,最開始等待客戶端連接,然后有一個客戶端連上了之后,啟動一個線程讀取客戶端的數據,然后主線程繼續等待客戶端連接。

該模型最大的問題就是缺乏彈性伸縮能力,當客戶端并發訪問量增加后,服務端的線程個數和客戶端并發訪問數呈1:1的正比關系,Java 中的線程也是比較寶貴的系統資源,線程數量快速膨脹后,系統的性能將急劇下降,隨著訪問量的繼續增大,系統最終就死掉了。當然不僅僅是 Java,我們直接設想假設有一萬個客戶端連接到服務端,服務端要開一萬個線程,那么這個時候服務端光開線程要占用多少資源?需要多大內存?操作系統為了調度這些線程 CPU 是不是也要被占用完了?

為了解決此問題,有人對服務器的線程模型進行優化,服務端采用線程池來處理多個客戶端請求。但是同樣是有問題的,

1. 線程總數有限,又要等待;

2. 多余的連接會堆積在任務隊列中,當任務隊列滿了,那么此時就開始啟用拒絕策略了,所以還是沒有從根本上解決問題。

2. NIO

BIO 最大的問題,在于 B,block,阻塞,所以只要解決了這個問題就可以,那么此時 NIO 應運而生,N 就是 non-block 的意思(Java 中是 new 的意思),同樣先看一個例子:

package cn.bridgeli.demo; import java.net.InetSocketAddress;import java.nio.ByteBuffer;import java.nio.channels.ServerSocketChannel;import java.nio.channels.SocketChannel;import java.util.LinkedList; /** * @author bridgeli */public class SocketNIO { public static void main(String[] args) throws Exception { LinkedList<SocketChannel> clients = new LinkedList<>(); ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();serverSocketChannel.bind(new InetSocketAddress(9090));serverSocketChannel.configureBlocking(false); while (true) { SocketChannel client = serverSocketChannel.accept(); if (null != client) {client.configureBlocking(false);System.out.println('client port: ' + client.socket().getPort());clients.add(client); } ByteBuffer buffer = ByteBuffer.allocateDirect(4096); for (SocketChannel c : clients) {int num = c.read(buffer);if (num > 0) { buffer.flip(); byte[] aaa = new byte[buffer.limit()]; buffer.get(aaa); String b = new String(aaa); System.out.println(c.socket().getPort() + ' : ' + b); buffer.clear();} }} } }

這個時候我們會發現連接和讀取都是非阻塞的了,由于都是非阻塞的,所以這就要求我們需要有一個集合,用來存儲所有的連接,然后從連接中讀取數據。這個模型解決了我們需要開線程的問題,沒循環一次,如果有新連接過來,我們就把連接放到集合中,然后挨個讀取連接中的數據,此時就不需要我們每連接每線程了,但是還是有一個問題,隨著連接的增加,我們的隊列會越來越大,而且我們每次都要遍歷所有的連接讀取數據,我們還假設有一萬個連接,但是前 9999 個連接都沒有數據,只有最后一個連接有數據,那前 9999 次讀取都是浪費。

3. 多路復用

為了解決 NIO 中無效讀取的問題,這個時候我們可以根據事件監聽,告訴操作系統說,我們監聽那些事件,然后當這些事件有數據到達時通知我們去讀取,例子如下:

package cn.bridgeli.demo; 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;import java.util.Set; /** * @author bridgeli */public class SocketMultiplexingIO { private ServerSocketChannel serverSocketChannel = null; private Selector selector = null; public void initServer() {try { serverSocketChannel = ServerSocketChannel.open(); serverSocketChannel.configureBlocking(false); serverSocketChannel.bind(new InetSocketAddress(9090)); selector = Selector.open(); serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);} catch (IOException e) { e.printStackTrace();} } public void start() {initServer();System.out.println('服務器啟動了...');try { while (true) { while (selector.select() > 0) { Set<SelectionKey> selectionKeys = selector.selectedKeys(); Iterator<SelectionKey> iterator = selectionKeys.iterator(); while (iterator.hasNext()) {SelectionKey key = iterator.next();iterator.remove();if (key.isAcceptable()) { acceptHandler(key);} else if (key.isReadable()) { readHandler(key);} }} }} catch (IOException e) { e.printStackTrace();} } public void acceptHandler(SelectionKey key) {try { ServerSocketChannel ssc = (ServerSocketChannel) key.channel(); SocketChannel client = ssc.accept(); client.configureBlocking(false); ByteBuffer buffer = ByteBuffer.allocate(8192); client.register(selector, SelectionKey.OP_READ, buffer); System.out.println('新客戶端:' + client.getRemoteAddress()); } catch (IOException e) { e.printStackTrace();} } public void readHandler(SelectionKey key) {SocketChannel client = (SocketChannel) key.channel();ByteBuffer buffer = (ByteBuffer) key.attachment();buffer.clear();int read = 0;try { while (true) {read = client.read(buffer);if (read > 0) { buffer.flip(); while (buffer.hasRemaining()) {client.write(buffer); } buffer.clear();} else if (read == 0) { break;} else { client.close(); break;} }} catch (IOException e) { e.printStackTrace(); } } public static void main(String[] args) {SocketMultiplexingIO service = new SocketMultiplexingIO();service.start(); }}

再多路復用中,有 poll、epoll、Selector 等實現方式,其中他們的區別是,poll 需要我們每次告訴操作系統說,我們都要關注哪些事件,而 epoll 是操作系統會開辟一塊內存區域,存儲下我們要關注的事件,不用每次都告訴操作系統我們關注哪些事件。

關于 BIO、NIO、多路復用,馬士兵教育的周志磊老師有一個很形象的例子。BIO 是阻塞的,所以需要我們每連接每線程,就相當于我們為每一輛車在收費站修建一條路,每來一輛車就要修一條路,我們我們自己從車上卸下裝的貨;NIO 是非阻塞的,我們就需要我們每次都跑到收費站,然后看我們修好的路上面車來了沒有,沒有來的話,等下次在看,來的話,我們卸下貨,再等下次看有沒有新貨;多路復用中的 poll,就是我們在收費站安裝一個電話機,然后我們每次打電話,我關注的哪些路是否有車來了,需要我卸貨,而 epoll 是我們不僅在收費站安裝了一個電話機,我們還留下了一個本子,我們每次打電話的時候,會把我們新關注的路告訴收費站,收費站在本子上記下我們關注的那些路,假設我們關注一萬條路,這樣就不需要我們每次在電話中每次把這一萬條路說一邊,問這些路是否有車來了,需要我們卸貨。

最后再說幾個小問題

1. 我們學習 IO 模型,IO 模型是操作系統提供給我們的接口,屬于系統調用,所以我們可以通過 strace 追蹤到每一個程序所執行的系統調用。命令如下:

strace -ff -o out + 要追蹤的進程

2. 當我們追蹤 BIO 的時候,因為 JDK 的優化,所以如果使用高版本的 JDK,也不會看到阻塞,這個時候你可以通過 JDK1.4 編譯運行(這也是為什么我們使用 lambda 表達式和 try-with-resource 的原因)

3. IO 調用屬于系統調用,所以從 BIO -> NIO -> 多路復用,是操作系統的進步,而我們各種變成語言寫的屬于應用,所以有沒有 異步非阻塞IO 模型,這樣看操作系統底層有沒有這樣的模型,需要操作系統給我們提供 異步非阻塞IO 相關的接口,我們的應用才能進一步優化

4. 我們通過 strace 追蹤到的每一個系統調用,都可以通過 man 命令查看文檔(僅限 linux 系統,非 Windows 系統),如果沒有 man 命令,安裝一下就可以了。

以上就是Java 中的io模型詳解的詳細內容,更多關于Java io模型的資料請關注好吧啦網其它相關文章!

標簽: Java
相關文章:
主站蜘蛛池模板: 郑州大巴车出租|中巴车租赁|旅游大巴租车|包车|郑州旅游大巴车租赁有限公司 | 知网论文检测系统入口_论文查重免费查重_中国知网论文查询_学术不端检测系统 | 泰国专线_泰国物流专线_广州到泰国物流公司-泰廊曼国际 | 实验室pH计|电导率仪|溶解氧测定仪|离子浓度计|多参数水质分析仪|pH电极-上海般特仪器有限公司 | 电动葫芦|防爆钢丝绳电动葫芦|手拉葫芦-保定大力起重葫芦有限公司 | 测试治具|过炉治具|过锡炉治具|工装夹具|测试夹具|允睿自动化设备 | 消防设施操作员考试报名时间,报名入口,报考条件 | 走心机厂家,数控走心机-台州博城智能科技有限公司 | 耐火浇注料-喷涂料-浇注料生产厂家_郑州市元领耐火材料有限公司 耐力板-PC阳光板-PC板-PC耐力板 - 嘉兴赢创实业有限公司 | 脉冲布袋除尘器_除尘布袋-泊头市净化除尘设备生产厂家 | 国际船舶网 - 船厂、船舶、造船、船舶设备、航运及海洋工程等相关行业综合信息平台 | ge超声波测厚仪-电动涂膜机-电动划格仪-上海洪富 | 网站建设-高端品牌网站设计制作一站式定制_杭州APP/微信小程序开发运营-鼎易科技 | arch电源_SINPRO_开关电源_模块电源_医疗电源-东佑源 | 云南丰泰挖掘机修理厂-挖掘机维修,翻新,再制造的大型企业-云南丰泰工程机械维修有限公司 | 地源热泵一体机,地源热泵厂家-淄博汇能环保设备有限公司 | 超声波电磁流量计-液位计-孔板流量计-料位计-江苏信仪自动化仪表有限公司 | 造价工程师网,考试时间查询,报名入口信息-网站首页 | 烟气在线监测系统_烟气在线监测仪_扬尘检测仪_空气质量监测站「山东风途物联网」 | 飞行者联盟-飞机模拟机_无人机_低空经济_航空技术交流平台 | 欧美日韩国产一区二区三区不_久久久久国产精品无码不卡_亚洲欧洲美洲无码精品AV_精品一区美女视频_日韩黄色性爱一级视频_日本五十路人妻斩_国产99视频免费精品是看4_亚洲中文字幕无码一二三四区_国产小萍萍挤奶喷奶水_亚洲另类精品无码在线一区 | 爱佩恒温恒湿测试箱|高低温实验箱|高低温冲击试验箱|冷热冲击试验箱-您身边的模拟环境试验设备技术专家-合作热线:400-6727-800-广东爱佩试验设备有限公司 | 2025黄道吉日查询、吉时查询、老黄历查询平台- 黄道吉日查询网 | 山东集装箱活动房|济南集装箱活动房-济南利森集装箱有限公司 | 车辆定位管理系统_汽车GPS系统_车载北斗系统 - 朗致物联 | 无尘烘箱_洁净烤箱_真空无氧烤箱_半导体烤箱_电子防潮柜-深圳市怡和兴机电 | PC构件-PC预制构件-构件设计-建筑预制构件-PC构件厂-锦萧新材料科技(浙江)股份有限公司 | 重庆监控_电子围栏设备安装公司_门禁停车场管理系统-劲浪科技公司 | 滚筒烘干机_转筒烘干机_滚筒干燥机_转筒干燥机_回转烘干机_回转干燥机-设备生产厂家 | 艺术漆十大品牌_艺术涂料加盟代理_蒙太奇艺术涂料厂家品牌|艺术漆|微水泥|硅藻泥|乳胶漆 | 广州物流公司_广州货运公司_广州回程车运输 - 万信物流 | 洛阳防爆合格证办理-洛阳防爆认证机构-洛阳申请国家防爆合格证-洛阳本安防爆认证代办-洛阳沪南抚防爆电气技术服务有限公司 | 粘度计NDJ-5S,粘度计NDJ-8S,越平水分测定仪-上海右一仪器有限公司 | 重庆网站建设,重庆网站设计,重庆网站制作,重庆seo,重庆做网站,重庆seo,重庆公众号运营,重庆小程序开发 | QQ房产导航-免费收录优秀房地产网站_房地产信息网 | 河南档案架,档案密集架,手动密集架,河南密集架批发/报价 | 比士亚-专业恒温恒湿酒窖,酒柜,雪茄柜的设计定制 | 彩超机-黑白B超机-便携兽用B超机-多普勒彩超机价格「大为彩超」厂家 | 湖南印刷厂|长沙印刷公司|画册印刷|挂历印刷|台历印刷|杂志印刷-乐成印刷 | 中矗模型-深圳中矗模型设计有限公司| 卫生纸复卷机|抽纸机|卫生纸加工设备|做卫生纸机器|小型卫生纸加工需要什么设备|卫生纸机器设备多少钱一台|许昌恒源纸品机械有限公司 |