<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
1)阻塞I/O(blocking I/O)
2)非阻塞I/O (nonblocking I/O)
3) I/O複用(select 和poll) (I/O multiplexing)
4)訊號驅動I/O (signal driven I/O (SIGIO))
5)非同步I/O (asynchronous I/O (the POSIX aio_functions))
前面四種都是同步io、第五種是非同步IO;
阻塞式:當程式沒有獲取到資料的時候,整個應用可能會產生阻塞,放棄了CPU執行,無法去做其他事情。
非阻塞式:不管有沒有獲取到資料,都必須立馬返回一個結果,如果沒有獲取到資料的情況下返回一個錯誤標記,根據錯誤的標記不斷輪詢。BIO屬於阻塞式的io操作。可以使用多執行緒實現非同步I0,同時處理多個請求。缺點:非常消耗伺服器資源CPU
BIO屬於阻塞式的io操作。
可以使用多執行緒實現非同步IO,同時處理多個請求。缺點:非常消耗伺服器資源CPU
當我們在呼叫一個io函數的時候,如果沒有獲取到資料的情況下,那麼就會一直等待;等待的過程中會導致整個應用程式一直是一個阻塞的過程,無法去做其他的實現。
IO複用機制:IO實際指的就是網路的IO、多路也就是多個不同的tcp連線;複用也就是指使用同一個執行緒合併處理多個不同的IO操作,這樣的話可以減少CPU資源。
發出一個請求實現觀察監聽,當有資料的時候直接走我們非同步回撥;
非同步io也就是發出請求資料之後,剩下的事情完全實現非同步完成
同步與非同步
站在多執行緒的角度總結:
同步整個應用程式碼執行順序是從上往下執行 並且返回到結果;
非同步:開啟多個不同的分支實現並行執行 每個執行緒互不影響;
站在web專案角度分析
預設的情況Http請求就是一個同步形式實現呼叫 基於請求與響應,如果我們響應非常耗時的話,會導致使用者端一直等待(使用者體驗非常不好)
Java的nio是在Jdk1.4版本之後推出了一套新的io方案,這種io方案對原有io做了一次效能上的升級
NIO翻譯成英文 no blocking io 簡稱為 nio 非阻塞io,不是new io。
比傳統的io支援了面向緩衝區、基於通道實現的io的方案。
BIO 與 NIO 區別:
Bio是一個阻塞式的io,它是西向與流傳輸也就是根據每個位元組實現傳輸效率非常低,
而我們的nio是雨向與緩衝區的非阻塞邊.其中最大的亮點:運多路複用機制,
多路實際上指的是多個不同的 tcp 連線。
複用:一個執行緒可以維護多個不同的io操作。
優點:佔用cpu資源非常小、保證執行緒安全問題。
IO 多路複用實現原理
使用一個Java案例來描述IO多路複用的思路:
public class SocketNioTcpServer { private static List<SocketChannel> listSocketChannel = new ArrayList<>(); private static ByteBuffer byteBuffer = ByteBuffer.allocate(512); public static void main(String[] args) { try { // 1.建立一個ServerSocketChannel ServerSocketChannel serverSocketChannel = ServerSocketChannel.open(); // 2. 繫結地址 ServerSocketChannel bind = serverSocketChannel.bind(new InetSocketAddress(8080)); serverSocketChannel.configureBlocking(false); while (true) { SocketChannel socketChannel = serverSocketChannel.accept(); if (socketChannel != null) { socketChannel.configureBlocking(false); listSocketChannel.add(socketChannel); } for (SocketChannel scl : listSocketChannel) { try { int read = scl.read(byteBuffer); if (read > 0) { byteBuffer.flip(); Charset charset = Charset.forName("UTF-8"); String receiveText = charset.newDecoder().decode (byteBuffer.asReadOnlyBuffer()).toString(); System.out.println("receiveText:" + receiveText); } } catch (Exception e) { e.printStackTrace(); } } } } catch (Exception e) { e.printStackTrace(); } } }
通道(Channel)
通常我們nio所有的操作都是通過通道開始的,所有的通道都會註冊到統一個選擇器(Selector)上實現管理,在通過選擇器將資料統一寫入到 buffer中。
緩衝區(Buffer)
Buffer本質上就是一塊記憶體區,可以用來讀取資料,也就先將資料寫入到緩衝區中、在統一的寫入到硬碟上。
選擇器(Selector)
Selector可以稱做為選擇器,也可以把它叫做多路複用器,可以在單執行緒的情況下可以去維護多個Channel,也可以去維護多個連線;
public class NIOServer { /** * 建立一個選擇器 */ private Selector selector; public void initServer(int port) throws IOException { // 獲得一個ServerSocketChannel通道 ServerSocketChannel serverSocketChannel = ServerSocketChannel.open(); // 設定通道為非阻塞 serverSocketChannel.configureBlocking(false); // 將該通道對應的ServerSocket繫結到port埠 serverSocketChannel.bind(new InetSocketAddress(port)); // 獲得一個通道管理器 this.selector = Selector.open(); // 將通道管理器和該通道繫結,併為該通道註冊SelectionKey.OP_ACCEPT事件,註冊該事件後, // 當該事件到達時,selector.select()會返回,如果該事件沒到達selector.select()會一直阻塞。 serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT); } public void listen() throws IOException { System.out.println("伺服器端啟動成功!"); // 輪詢存取selector while (true) { // 當註冊的事件到達時,方法返回;否則,該方法會一直阻塞 int select = selector.select(); if (select == 0) { continue; } // 獲得selector中選中的項的迭代器,選中的項為註冊的事件 Iterator<SelectionKey> ite = this.selector.selectedKeys().iterator(); while (ite.hasNext()) { SelectionKey key = (SelectionKey) ite.next(); // 刪除已選的key,以防重複處理 ite.remove(); if (key.isAcceptable()) {// 使用者端請求連線事件 ServerSocketChannel server = (ServerSocketChannel) key.channel(); // 獲得和使用者端連線的通道 SocketChannel channel = server.accept(); // 設定成非阻塞 channel.configureBlocking(false); // 在和使用者端連線成功之後,為了可以接收到使用者端的資訊,需要給通道設定讀的許可權。 channel.register(this.selector, SelectionKey.OP_READ); } else if (key.isReadable()) {// 獲得了可讀的事件 read(key); } } } } public void read(SelectionKey key) throws IOException { // 伺服器可讀取訊息:得到事件發生的Socket通道 SocketChannel channel = (SocketChannel) key.channel(); // 建立讀取的緩衝區 ByteBuffer buffer = ByteBuffer.allocate(512); channel.read(buffer); byte[] data = buffer.array(); String msg = new String(data).trim(); System.out.println("伺服器端收到資訊:" + msg); ByteBuffer outBuffer = ByteBuffer.wrap(msg.getBytes("utf-8")); channel.write(outBuffer);// 將訊息回送給使用者端 } public static void main(String[] args) throws IOException { NIOServer server = new NIOServer(); server.initServer(8000); server.listen(); } }
Redis官方沒有windows版本redis,只有linux版本的reids。
Redis的底層是採用nio 多路io複用機制實現對多個不同的連線(tcp)實現io的複用;能夠非常好的支援高並行,同時能夠先天性支援執行緒安全的問題。為什麼現場安全?因為使用一個執行緒維護多個不同的io操作 原理使用nio的選擇器,將多個不同的Channel統一交給我們的selector(選擇器管理)。
但是nio的實現在不同的作業系統上存在差別:在我們windows作業系統上使用 select 實現輪訓機制、在linux作業系統使用epoll
備註:windows作業系統是沒有epoll
在windows作業系統中使用select實現輪訓機制時間複雜度是為 o(n),而且這種情況也會存在空輪訓的情況,效率非常低、其次預設對我們的輪訓有一定限制,所以這樣的話很難支援上萬tcp連線。
所以在這時候linux操作就出現epoll實現事件驅動回撥形式通知,不會存在空輪訓的情況,只是對活躍的socket實現主動回撥,這樣的效能有很大的提升 所以時間複雜度為是o(1)
注意:windows作業系統沒有epoll、只有linux作業系統有。
所以為什麼Nginx、redis能夠支援非常高的並行 最終都是靠的linux版本的 io 多路複用機制epoll
到此這篇關於Netty與NIO超詳細講解的文章就介紹到這了,更多相關Netty NIO內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45