日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術(shù)文章
文章詳情頁

Java 中的io模型詳解

瀏覽:181日期: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 也是阻塞的,也就是說我們的服務(wù)器起來之后,首先會在 accept 處阻塞,等待客戶端連接,但有一個客戶端連接的時候,我們可以從客戶端處讀取數(shù)據(jù),這個時候也是阻塞的,所以我們的系統(tǒng)只能是單連接的,當(dāng)有多個客戶端連接的時候,只能一個一個的排著隊連接,然后從客戶端中讀取數(shù)據(jù),為了實現(xiàn)多連接,這就要求我們必須啟用線程來解決,最開始等待客戶端連接,然后有一個客戶端連上了之后,啟動一個線程讀取客戶端的數(shù)據(jù),然后主線程繼續(xù)等待客戶端連接。

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

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

1. 線程總數(shù)有限,又要等待;

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

2. NIO

BIO 最大的問題,在于 B,block,阻塞,所以只要解決了這個問題就可以,那么此時 NIO 應(yīng)運而生,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();} }} } }

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

3. 多路復(fù)用

為了解決 NIO 中無效讀取的問題,這個時候我們可以根據(jù)事件監(jiān)聽,告訴操作系統(tǒng)說,我們監(jiān)聽那些事件,然后當(dāng)這些事件有數(shù)據(jù)到達(dá)時通知我們?nèi)プx取,例子如下:

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('服務(wù)器啟動了...');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(); }}

再多路復(fù)用中,有 poll、epoll、Selector 等實現(xiàn)方式,其中他們的區(qū)別是,poll 需要我們每次告訴操作系統(tǒng)說,我們都要關(guān)注哪些事件,而 epoll 是操作系統(tǒng)會開辟一塊內(nèi)存區(qū)域,存儲下我們要關(guān)注的事件,不用每次都告訴操作系統(tǒng)我們關(guān)注哪些事件。

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

最后再說幾個小問題

1. 我們學(xué)習(xí) IO 模型,IO 模型是操作系統(tǒng)提供給我們的接口,屬于系統(tǒng)調(diào)用,所以我們可以通過 strace 追蹤到每一個程序所執(zhí)行的系統(tǒng)調(diào)用。命令如下:

strace -ff -o out + 要追蹤的進(jìn)程

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

3. IO 調(diào)用屬于系統(tǒng)調(diào)用,所以從 BIO -> NIO -> 多路復(fù)用,是操作系統(tǒng)的進(jìn)步,而我們各種變成語言寫的屬于應(yīng)用,所以有沒有 異步非阻塞IO 模型,這樣看操作系統(tǒng)底層有沒有這樣的模型,需要操作系統(tǒng)給我們提供 異步非阻塞IO 相關(guān)的接口,我們的應(yīng)用才能進(jìn)一步優(yōu)化

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

以上就是Java 中的io模型詳解的詳細(xì)內(nèi)容,更多關(guān)于Java io模型的資料請關(guān)注好吧啦網(wǎng)其它相關(guān)文章!

標(biāo)簽: Java
相關(guān)文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
美国三级日本三级久久99 | 日本大胆欧美人术艺术动态| 国产专区精品| 神马久久午夜| 麻豆91精品91久久久的内涵| 久久免费福利| 欧美黄色网页| 伊人久久成人| 国产精品一区2区3区| 国产精品色在线网站| 国产精品对白| 在线亚洲人成| 欧美精品一区二区三区精品| 欧美在线观看视频一区| 亚洲欧美高清| 国产精品密蕾丝视频下载| 中文字幕在线官网| 欧美一级精品| 亚洲日本免费电影| 国产激情综合| 欧美www视频在线观看| 欧产日产国产精品视频| 蜜臀av免费一区二区三区| 99精品在线免费在线观看| 国产精品亚洲片在线播放| 美国三级日本三级久久99| 日韩电影免费在线观看| 国产亚洲精品久久久久婷婷瑜伽| 久久av超碰| 日日摸夜夜添夜夜添国产精品| 国产精品一区免费在线| 97精品国产福利一区二区三区| 日韩中文字幕1| 久久毛片亚洲| 美女国产精品久久久| 在线观看亚洲精品福利片| 久久久久久黄| 久久久久黄色| 中文字幕av一区二区三区人| 黄色在线网站噜噜噜| 一区二区三区四区日韩| 激情黄产视频在线免费观看| 日韩精品中文字幕吗一区二区| 国产日韩欧美高清免费| 男女激情视频一区| 人在线成免费视频| 国产精品白浆| 日本久久一区| 免费在线欧美视频| 激情婷婷综合| 视频小说一区二区| 精品网站aaa| 69堂免费精品视频在线播放| 美女精品在线| 少妇精品久久久一区二区| 久久精品国产亚洲夜色av网站 | av最新在线| 久久99偷拍| 嫩草伊人久久精品少妇av杨幂| 正在播放日韩精品| 久久久国产精品网站| 亚洲三级网址| 日韩综合一区二区| 视频一区二区三区在线| 欧美亚洲在线日韩| 欧美日韩高清| 在线观看免费一区二区| 亚洲精品一区二区在线看| 国产乱码午夜在线视频| 天堂√8在线中文| 精品免费视频| 日本v片在线高清不卡在线观看| 亚洲三级网址| 欧美日韩伊人| 久久97视频| 日产精品一区| 欧美日韩三区| 日韩国产在线观看一区| 美女视频免费精品| 精品免费av在线| 狠狠色综合网| 蜜臀精品一区二区三区在线观看| 亚洲精一区二区三区| 日本成人手机在线| 久久影院一区二区三区| 欧美色图一区| 国产日韩欧美一区| 成人片免费看| 亚洲免费成人av在线| 久久一区视频| 日韩午夜免费| 国产一区一一区高清不卡| 久久久人人人| 久久精品 人人爱| 欧美日韩精品在线一区| 久久超碰99| 亚州av一区| 99久久亚洲精品| 日韩欧美中文字幕电影| 久久一区欧美| 日本欧美大码aⅴ在线播放| 国产综合色区在线观看| 亚洲精品乱码久久久久久蜜桃麻豆| 久草精品视频| 欧美亚洲三区| 91超碰国产精品| 国语精品一区| 国产精品亚洲一区二区在线观看| 美日韩精品视频| 欧美日韩国产免费观看视频| 日韩精品三级| 久久伦理在线| 欧美色图一区| 毛片在线网站| 精品伊人久久久| 久久天堂影院| 日产精品一区二区| 色综合视频一区二区三区日韩 | 在线视频精品| 久久狠狠久久| 国产精品毛片在线| 在线看片国产福利你懂的| 国产精品色在线网站| 亚洲综合色婷婷在线观看| 欧美日韩国产亚洲一区| 国产成人精品亚洲日本在线观看| 91精品国产经典在线观看| 国产综合婷婷| 成人午夜在线| 精品国产91| 精品国产精品国产偷麻豆| 日本va欧美va瓶| 日本亚洲视频在线| 欧美日韩18| 国产精品美女久久久久久不卡| 亚洲2区在线| 日韩av资源网| 国产精品欧美大片| 国产精品调教| 国产一区二区三区四区| 福利在线免费视频| 亚洲大片在线| 中文国产一区| 蜜桃久久久久久久| 久久精品99国产精品| 国产精品v日韩精品v欧美精品网站 | 亚洲精品美女| re久久精品视频| 欧美精品一二| 亚洲免费福利一区| 久久影院资源站| 999国产精品永久免费视频app| 国产中文一区| 亚洲精品一级| 开心激情综合| 高清精品久久| 亚洲深夜福利| 日韩精品欧美精品| 伊人久久av| 韩日一区二区| 激情综合激情| 国产日韩亚洲| 日韩精品麻豆| 日本vs亚洲vs韩国一区三区二区| 精品久久亚洲| 免费精品视频| 精品欠久久久中文字幕加勒比| 国产综合精品一区| 欧美亚洲三区| 1024精品久久久久久久久| 欧美伊人久久| 国产亚洲亚洲| 国产亚洲一卡2卡3卡4卡新区| 久久精品亚洲欧美日韩精品中文字幕| 日欧美一区二区| 欧美午夜精品一区二区三区电影| 国产欧美一级| 在线亚洲精品| 久久精品亚洲人成影院| 久久影视三级福利片| 日本不卡高清视频| 日韩有吗在线观看| 亚洲狼人精品一区二区三区| 91视频精品| 青青草精品视频| 伊人成人在线视频| 日韩精品影视| 国产精品久久久免费| 免费在线欧美视频| 午夜影院欧美| 999精品色在线播放| 国产一区国产二区国产三区| 日韩国产一区二| 一本色道精品久久一区二区三区| 亚洲国产成人二区| 欧美一区91| 欧美一区二区三区久久精品| 免费观看亚洲| 最新国产精品| 蜜桃91丨九色丨蝌蚪91桃色|