gmnon.cn-疯狂蹂躏欧美一区二区精品,欧美精品久久久久a,高清在线视频日韩欧美,日韩免费av一区二区

站長資訊網
最全最豐富的資訊網站

帶你完全掌握Java NIO(總結分享)

本篇文章給大家帶來了關于java的相關知識,其中主要介紹了NIO的相關問題,包括了NIO核心、BIO與NIO比較、通過NIO實現簡單的服務端客戶端通信,希望對大家有幫助。

帶你完全掌握Java NIO(總結分享)

推薦學習:《java教程》

一、Java思維導圖

帶你完全掌握Java NIO(總結分享)

二、I/O模型

I/O模型的本質是用什么樣的通道進行數據的發送和接收,很大程度上決定了程序通信的性能。
Java共支持三種網絡編程模型:BIO、NIO、AIO

  • BIO:同步并阻塞,服務實現模式為一個連接一個線程,即客戶端有一個連接請求時,服務端就需要啟動一個線程進行處理。

  • NIO: 同步非阻塞,服務器實現模式為一個線程處理多個請求連接,即客戶端發送的請求都會注冊到多路復用器上,多路復用器輪詢到連接有I/O請求就進行處理。

  • AIO:異步非阻塞,AIO引入異步通道的概念,采用了Proactor模式,簡化了程序編寫,有效的請求才啟動線程,它的特點是先由操作系統完成后才通知服務端。

三、BIO、NIO、AIO應用場景

  • BIO方式適用于連接數目比較小且固定的架構,這種方式對服務器資源要求比較高, 并發局限于應用中,JDK1.4以前的唯一選擇,但程序簡單易理解。

  • NIO方式適用于連接數目多且連接比較短(輕操作)的架構,比如聊天服務器,彈幕 系統,服務器間通訊等。編程比較復雜,JDK1.4開始支持。

  • AIO方式使用于連接數目多且連接比較長(重操作)的架構,比如相冊服務器,充分 調用OS參與并發操作,編程比較復雜,JDK7開始支持

四、BIO編程簡單流程

  • 服務器端啟動一個ServerSocket;

  • 客戶端啟動Socket對服務器進行通 信,默認情況下服務器端需要對每 個客戶 建立一個線程與之通訊;

  • 客戶端發出請求后, 先咨詢服務器 是否有線程響應,如果沒有則會等 待,或者被拒絕;

  • 如果有響應,客戶端線程會等待請 求結束后,在繼續執行;

五、NIO核心

NIO 有三大核心部分:Selector(選擇器)、Channel(通道)、Buffer(緩沖區)。
NIO是面向緩沖區,或者說面向塊編程,數據讀取到一個 它稍后處理的緩沖區,需要時可在緩沖區中前后移動,這就 增加了處理過程中的靈活性,使用它可以提供非阻塞式的高伸縮性網絡。
HTTP2.0使用了多路復用的技術,做到同一個連接并發處理多個請求,而且并發請求 的數量比HTTP1.1大了好幾個數量級。
簡而言之,NIO可以一個線程處理多個請求。

六、BIO與NIO比較

  • BIO 以流的方式處理數據,而 NIO 以塊的方式處理數據,塊 I/O 的效率比流 I/O 高很多;

  • BIO 是阻塞的,NIO 則是非阻塞的;

  • BIO基于字節流和字符流進行操作,而 NIO 基于 Channel(通道)和 Buffer(緩沖區)進 行操作,數據總是從通道讀取到緩沖區中,或者從緩沖區寫入到通道中。Selector(選擇器)用于監聽多個通道的事件(比如:連接請求,數據到達等),因 此使用單個線程就可以監聽多個客戶端通道。

七、NIO 三大核心原理示意圖

帶你完全掌握Java NIO(總結分享)
流程圖說明:

  • Selector 對應一個線程, 一個線程對應多個channel(連接);

  • 該圖反應了有三個channel 注冊到 該selector //程序;

  • 每個channel 都會對應一個Buffer;

  • 程序切換到哪個channel 是有事件決定的, Event 就是一個重要的概念;

  • Selector 會根據不同的事件,在各個通道上切換;

  • Buffer 就是一個內存塊 , 底層是有一個數組;

  • 數據的讀取寫入是通過Buffer, 這個和BIO , BIO 中要么是輸入流,或者是 輸出流, 不能雙向,但是NIO的Buffer 是可以讀也可以寫, 需要 flip 方法切換;

  • channel 是雙向的, 可以返回底層操作系統的情況, 比如Linux , 底層的操作系統 通道就是雙向的;

八、緩沖區(buffer)

緩沖區本質上是一個可以讀寫數據的內存塊,可以理解成是一個 容器對象(含數組),該對象提供了一組方法,可以更輕松地使用內存塊,,緩沖區對 象內置了一些機制,能夠跟蹤和記錄緩沖區的狀態變化情況。Channel 提供從文件、 網絡讀取數據的渠道,但是讀取或寫入的數據都必須經由 Buffer。
在 NIO 中,Buffer 是一個頂層父類,它是一個抽象類。

1、常用Buffer子類一覽

  • ByteBuffer,存儲字節數據到緩沖區;

  • ShortBuffer,存儲字符串數據到緩沖區;

  • CharBuffer,存儲字符數據到緩沖區;

  • IntBuffer,存儲整數數據到緩沖區;

  • LongBuffer,存儲長整型數據到緩沖區;

  • DoubleBuffer,存儲小數到緩沖區;

  • FloatBuffer,存儲小數到緩沖區;

2、buffer四大屬性

  • mark:標記

  • position:位置,下一個要被讀或寫的元素的索引, 每次讀寫緩沖區數據時都會改變改值, 為下次讀寫作準備。

  • limit:表示緩沖區的當前終點,不能對緩沖區 超過極限的位置進行讀寫操作。且極限 是可以修改的

  • capacity:容量,即可以容納的最大數據量;在緩 沖區創建時被設定并且不能改變。

帶你完全掌握Java NIO(總結分享)

3、buffer常用api

JDK1.4時,引入的api

  • public final int capacity( )//返回此緩沖區的容量
  • public final int position( )//返回此緩沖區的位置
  • public final Buffer position (int newPositio)//設置此緩沖區的位置
  • public final int limit( )//返回此緩沖區的限制
  • public final Buffer limit (int newLimit)//設置此緩沖區的限制
  • public final Buffer mark( )//在此緩沖區的位置設置標記
  • public final Buffer reset( )//將此緩沖區的位置重置為以前標記的位置
  • public final Buffer clear( )//清除此緩沖區, 即將各個標記恢復到初始狀態,但是數據并沒有真正擦除, 后面操作會覆蓋
  • public final Buffer flip( )//反轉此緩沖區
  • public final Buffer rewind( )//重繞此緩沖區
  • public final int remaining( )//返回當前位置與限制之間的元素數
  • public final boolean hasRemaining( )//告知在當前位置和限制之間是否有元素
  • public abstract boolean isReadOnly( );//告知此緩沖區是否為只讀緩沖區

JDK1.6時引入的api

  • public abstract boolean hasArray();//告知此緩沖區是否具有可訪問的底層實現數組
  • public abstract Object array();//返回此緩沖區的底層實現數組
  • public abstract int arrayOffset();//返回此緩沖區的底層實現數組中第一個緩沖區元素的偏移量
  • public abstract boolean isDirect();//告知此緩沖區是否為直接緩沖區

帶你完全掌握Java NIO(總結分享)

九、通道(channel)

1、基本介紹

(1)NIO的通道類似于流

  • 通道可以同時進行讀寫,而流只能讀或者只能寫;
  • 通道可以實現異步讀寫數據
  • 通道可以從緩沖讀數據,也可以寫數據到緩沖

(2)BIO 中的 stream 是單向的,例如 FileInputStream 對 象只能進行讀取數據的操作,而 NIO 中的通道 (Channel)是雙向的,可以讀操作,也可以寫操作。
(3)Channel在NIO中是一個接口
(4)常用的 Channel 類有:FileChannel、 DatagramChannel、ServerSocketChannel 和 SocketChannel。ServerSocketChanne 類似 ServerSocket , SocketChannel 類似 Socket。
(5)FileChannel 用于文件的數據讀寫, DatagramChannel 用于 UDP 的數據讀寫, ServerSocketChannel 和 SocketChannel 用于 TCP 的數據讀寫。

2、FileChannel

FileChannel主要用來對本地文件進行 IO 操作,常見的方法有:

  • read,從通道讀取數據并放到緩沖區中

  • write,把緩沖區的數據寫到通道中

  • transferFrom,從目標通道 中復制數據到當前通道

  • transferTo,把數據從當 前通道復制給目標通道

3、關于Buffer 和 Channel的注意事項和細節

  • ByteBuffer 支持類型化的put 和 get, put 放入的是什么數據類型,get就應該使用 相應的數據類型來取出,否則可能有 BufferUnderflowException 異常。

  • 可以將一個普通Buffer 轉成只讀Buffer。

  • NIO 還提供了 MappedByteBuffer, 可以讓文件直接在內存(堆外的內存)中進 行修改, 而如何同步到文件由NIO 來完成。

  • NIO 還支持 通過多個 Buffer (即 Buffer 數組) 完成讀寫操作,即 Scattering 和 Gathering。

十、Selector(選擇器)

1、基本介紹

  • Java 的 NIO,用非阻塞的 IO 方式。可以用一個線程,處理多個的客戶端連 接,就會使用到Selector(選擇器)。

  • Selector 能夠檢測多個注冊的通道上是否有事件發生,如果有事件發生,便獲取事件然 后針對每個事件進行相應的處理。這樣就可以只用一個單線程去管理多個 通道,也就是管理多個連接和請求。

  • 只有在 連接/通道 真正有讀寫事件發生時,才會進行讀寫,就大大地減少 了系統開銷,并且不必為每個連接都創建一個線程,不用去維護多個線程。

  • 避免了多線程之間的上下文切換導致的開銷。

2、selector的相關方法

  • open();//得到一個選擇器對象

  • select(long timeout);//監控所有注冊的通道,當其 中有 IO 操作可以進行時,將 對應的 SelectionKey 加入到內部集合中并返回,參數用來 設置超時時間

  • selectedKeys();//從內部集合中得 到所有的 SelectionKey。

3、注意事項

NIO中的 ServerSocketChannel功能類似ServerSocket,SocketChannel功能類 似Socket。

十一、通過NIO實現簡單的服務端客戶端通信

1、服務端

package com.nezha.guor.nio;import java.io.IOException;import java.net.InetSocketAddress;import java.nio.ByteBuffer;import java.nio.channels.*;import java.util.Iterator;public class NioServer {     private Selector selector;     private ServerSocketChannel serverSocketChannel;     private static final int PORT = 8080;      public NioServer() {         try {             //獲得選擇器             selector = Selector.open();             serverSocketChannel =  ServerSocketChannel.open();             //綁定端口             serverSocketChannel.socket().bind(new InetSocketAddress(PORT));             //設置非阻塞模式             serverSocketChannel.configureBlocking(false);             //將該ServerSocketChannel 注冊到selector             serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);         }catch (IOException e) {             System.out.println("NioServer error:"+e.getMessage());         }     }      public void listen() {          System.out.println("監聽線程啟動: " + Thread.currentThread().getName());         try {             while (true) {                 int count = selector.select();                 if(count > 0) {                     //遍歷得到selectionKey集合                     Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();                     while (iterator.hasNext()) {                         SelectionKey key = iterator.next();                          if(key.isAcceptable()) {                             SocketChannel sc = serverSocketChannel.accept();                             sc.configureBlocking(false);                             sc.register(selector, SelectionKey.OP_READ);                             System.out.println(sc.getRemoteAddress() + " 上線 ");                         }                         //通道發送read事件,即通道是可讀的狀態                         if(key.isReadable()) {                             getDataFromChannel(key);                         }                         //當前的key 刪除,防止重復處理                         iterator.remove();                     }                 } else {                     System.out.println("等待中");                 }             }         }catch (Exception e) {             System.out.println("listen error:"+e.getMessage());         }     }      private void getDataFromChannel(SelectionKey key) {         SocketChannel channel = null;         try {             channel = (SocketChannel) key.channel();             ByteBuffer buffer = ByteBuffer.allocate(1024);              int count = channel.read(buffer);             //根據count的值做處理             if(count > 0) {                 String msg = new String(buffer.array());                 System.out.println("來自客戶端: " + msg);                  //向其它的客戶端轉發消息(排除自己)                 sendInfoToOtherClients(msg, channel);             }         }catch (IOException e) {             try {                 System.out.println(channel.getRemoteAddress() + " 離線了");                 //取消注冊                 key.cancel();             }catch (IOException ex) {                 System.out.println("getDataFromChannel error:"+ex.getMessage());             }         }finally {             try {                 channel.close();             }catch (IOException ex) {                 System.out.println("channel.close() error:"+ex.getMessage());             }         }     }      //轉發消息給其它客戶(通道)     private void sendInfoToOtherClients(String msg, SocketChannel self ) throws  IOException{         System.out.println("服務器轉發消息中...");         System.out.println("服務器轉發數據給客戶端線程: " + Thread.currentThread().getName());         //遍歷 所有注冊到selector 上的 SocketChannel,并排除 self         for(SelectionKey key: selector.keys()) {             Channel targetChannel = key.channel();              //排除自己             if(targetChannel instanceof  SocketChannel && targetChannel != self) {                 SocketChannel dest = (SocketChannel)targetChannel;                 //將信息存儲到buffer                 ByteBuffer buffer = ByteBuffer.wrap(msg.getBytes());                 //將buffer數據寫入通道                 dest.write(buffer);             }         }     }      public static void main(String[] args) {         //創建服務器對象         NioServer nioServer = new NioServer();         nioServer.listen();     }}

2、客戶端

package com.nezha.guor.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;import java.util.Scanner;public class NioClient {     private final int PORT = 8080; //服務器端口     private Selector selector;     private SocketChannel socketChannel;     private String username;      public NioClient() throws IOException {         selector = Selector.open();         socketChannel = socketChannel.open(new InetSocketAddress("127.0.0.1", PORT));         //設置非阻塞         socketChannel.configureBlocking(false);         //將channel注冊到selector         socketChannel.register(selector, SelectionKey.OP_READ);         username = socketChannel.getLocalAddress().toString().substring(1);         System.out.println(username + " is ok...");     }      //向服務器發送消息     public void sendInfo(String info) {         info = username + " 說:" + info;         try {             socketChannel.write(ByteBuffer.wrap(info.getBytes()));         }catch (IOException e) {             System.out.println("sendInfo error:"+e.getMessage());         }     }      //讀取從服務器端回復的消息     public void readInfo() {         try {             int readChannels = selector.select();             if(readChannels > 0) {                 Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();                 while (iterator.hasNext()) {                     SelectionKey key = iterator.next();                     if(key.isReadable()) {                         //得到相關的通道                         SocketChannel sc = (SocketChannel) key.channel();                         //得到一個Buffer                         ByteBuffer buffer = ByteBuffer.allocate(1024);                         //讀取                         sc.read(buffer);                         //把讀到的緩沖區的數據轉成字符串                         String msg = new String(buffer.array());                         System.out.println(msg.trim());                     }                 }                 iterator.remove(); //刪除當前的selectionKey, 防止重復操作             } else {                 System.out.println("沒有可以用的通道...");             }         }catch (Exception e) {             System.out.println("readInfo error:"+e.getMessage());         }     }      public static void main(String[] args) throws Exception {         NioClient nioClient = new NioClient();         new Thread() {             public void run() {                 while (true) {                     nioClient.readInfo();                     try {                         Thread.currentThread().sleep(2000);                     }catch (InterruptedException e) {                         System.out.println("sleep error:"+e.getMessage());                     }                 }             }         }.start();          //發送數據給服務器端         Scanner scanner = new Scanner(System.in);          while (scanner.hasNextLine()) {             nioClient.sendInfo(scanner.nextLine());         }     }}

3、控制臺輸出

帶你完全掌握Java NIO(總結分享)
帶你完全掌握Java NIO(總結分享)

推薦學習:《java教程》

贊(0)
分享到: 更多 (0)
?
網站地圖   滬ICP備18035694號-2    滬公網安備31011702889846號
gmnon.cn-疯狂蹂躏欧美一区二区精品,欧美精品久久久久a,高清在线视频日韩欧美,日韩免费av一区二区
今天免费高清在线观看国语| 日本xxx免费| 免费观看黄色的网站| 97超碰人人澡| 992kp免费看片| 国内外免费激情视频| 狠狠躁狠狠躁视频专区| 亚洲第一页在线视频| 国产精品涩涩涩视频网站| 亚洲熟妇无码一区二区三区导航| 黄色免费网址大全| 色婷婷综合久久久久中文字幕| 亚洲精品天堂成人片av在线播放| 免费av不卡在线| 日本精品一区在线| 樱花草www在线| 国产一级免费大片| 亚洲在线观看网站| 一级做a爱视频| 日本丰满少妇黄大片在线观看| 九九热免费在线观看| 最近免费中文字幕中文高清百度| 日本国产在线播放| 国产无色aaa| 欧美爱爱视频免费看| 97在线播放视频| 亚洲第一色av| 国产精品无码人妻一区二区在线| 亚洲欧美一二三| 色一情一区二区三区| 天天成人综合网| 国产激情片在线观看| 免费成人在线视频网站| 97超碰人人澡| 日日躁夜夜躁aaaabbbb| 99久re热视频精品98| 永久免费看av| caoporn超碰97| 久久人人爽人人片| 日本少妇高潮喷水视频| 超碰成人在线播放| 日日碰狠狠添天天爽超碰97| 蜜臀视频一区二区三区| 国产一级黄色录像片| 欧美午夜aaaaaa免费视频| 精品人妻大屁股白浆无码| 亚洲性生活网站| 国产69精品久久久久久久| 污色网站在线观看| 久久久精品在线视频| 国产a级黄色大片| 黄色一级片网址| 国产成年人视频网站| 成人免费视频久久| 成人在线视频一区二区三区| 一区二区三区 日韩| ww国产内射精品后入国产| 天天做天天爱天天高潮| 色哟哟精品视频| 国产在线观看福利| 国产片侵犯亲女视频播放| 日韩欧美亚洲另类| 制服丝袜综合网| 亚洲激情在线看| 亚洲一级片网站| 日韩av加勒比| 99九九精品视频| 欧美成人乱码一二三四区免费| 久久精品午夜福利| 已婚少妇美妙人妻系列| 国产精品99久久免费黑人人妻| 欧美一级视频在线播放| 毛片在线视频播放| www.国产区| 亚洲欧美天堂在线| 国产一二三四五| 国产精品裸体瑜伽视频| 欧美日韩在线不卡视频| 色乱码一区二区三区在线| 91香蕉国产线在线观看| 欧美精品自拍视频| 亚洲天堂网一区| 天堂在线精品视频| 欧美精品自拍视频| 91看片破解版| cao在线观看| 自拍偷拍一区二区三区四区| 日本丰满少妇黄大片在线观看| 日韩 欧美 视频| 手机免费av片| 国产在线青青草| 久久精品xxx| 簧片在线免费看| 国产资源在线免费观看| 色婷婷一区二区三区av免费看| 日本www在线视频| 黄色小视频大全| 青青草原国产免费| 91香蕉视频污版| 日韩欧美亚洲天堂| 久草视频这里只有精品| 亚洲小说欧美另类激情| 91国内在线播放| 日韩欧美在线免费观看视频| 国产在线播放观看| 国产情侣第一页| 日本一级黄视频| 免费在线看黄色片| 99re99热| 成人污网站在线观看| 免费日韩在线观看| 精品久久久久久无码中文野结衣| 超碰免费在线公开| 好吊色这里只有精品| 久久久国内精品| 久久精品无码中文字幕| 老子影院午夜伦不卡大全| 免费人成自慰网站| 国产精品亚洲a| 99九九精品视频| 国产青草视频在线观看| 免费无遮挡无码永久视频| 白嫩少妇丰满一区二区| 蜜臀av免费观看| 做爰高潮hd色即是空| 大陆极品少妇内射aaaaaa| 国产白丝袜美女久久久久| 九一精品在线观看| 色乱码一区二区三区熟女| 久久成人福利视频| 可以在线看的黄色网址| 经典三级在线视频| 99精品免费在线观看| 艳母动漫在线免费观看| 男人天堂999| 欧美一级中文字幕| 久热精品在线播放| www.中文字幕在线| 青娱乐精品在线| 亚洲熟妇无码另类久久久| 一级黄色免费在线观看| 91av在线免费播放| 国产黄视频在线| 日本黄色a视频| 五月婷婷狠狠操| 欧美不卡在线播放| 懂色av粉嫩av蜜臀av| 538任你躁在线精品免费| 人妻有码中文字幕| 五十路熟女丰满大屁股| 日本三级中文字幕在线观看| 日本人视频jizz页码69| 久久黄色免费看| av免费中文字幕| 国产主播在线看| 久久精品国产精品亚洲色婷婷| 51xx午夜影福利| 樱空桃在线播放| 少妇一晚三次一区二区三区| 日本三级中文字幕在线观看| 大地资源网在线观看免费官网| 国产欧美一区二| 中国一级黄色录像| 日本aa在线观看| 欧美变态另类刺激| 久久黄色片视频| 亚洲人视频在线| 日韩一二区视频| 欧美 日本 亚洲| 网站一区二区三区| 性久久久久久久久久久久久久| 干日本少妇视频| 无码aⅴ精品一区二区三区浪潮 | 奇米视频7777| 特色特色大片在线| 欧美精品色婷婷五月综合| 99热这里只有精品在线播放| 手机在线视频一区| 激情成人开心网| 在线观看免费不卡av| 韩日视频在线观看| 欧美午夜aaaaaa免费视频| 蜜桃网站在线观看| 一本岛在线视频| 国产免费黄色一级片| 在线播放黄色av| 青青青在线播放| 欧美日韩一道本| 18视频在线观看娇喘| 丰满少妇在线观看| 国产免费xxx| 91xxx视频| 亚洲男人天堂2021| 嫩草影院国产精品| ww国产内射精品后入国产| 91九色丨porny丨国产jk| 亚洲国产精品影视| 国产不卡的av| 污污的视频免费观看| 中文字幕第一页在线视频|