亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Java NIO開發的實例介紹

發布時間:2021-08-31 16:49:28 來源:億速云 閱讀:122 作者:chen 欄目:編程語言

本篇內容介紹了“Java NIO開發的實例介紹”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!

首先來看下傳統的阻塞型網絡I/O的不足

Java 平臺傳統的I/O 系統都是基于Byte(字節)和Stream(數據流)的,相應的I/O 操作都是阻塞型的,所以服務器程序也采用阻塞型I/O 進行數據的讀、寫操作。本文以TCP長連接模式來討論并發型服務器的相關設計,為了實現服務器程序的并發性要求,系統由一個單獨的主線程來監聽用戶發起的連接請求,一直處于阻塞狀態;當有用戶連接請求到來時,程序都會啟一個新的線程來統一處理用戶數據的讀、寫操作。

這種模式的優點是簡單、實用、易管理;然而缺點也是顯而易見的:由于是為每一個客戶端分配一個線程來處理輸入、輸出數據,其線程與客戶機的比例近似為1:1,隨著線程數量的不斷增加,服務器啟動了大量的并發線程,會大大加大系統對線程的管理開銷,這將成為吞吐量瓶頸的主要原因;其次由于底層的I/O 操作采用的同步模式,I/O 操作的阻塞管理粒度是以服務于請求的線程為單位的,有可能大量的線程會閑置,處于盲等狀態,造成I/O資源利用率不高,影響整個系統的性能。

對于并發型服務器,系統用在阻塞型I/O 等待和線程間切換的時間遠遠多于CPU 在內存中處理數據的時間,因此傳統的阻塞型I/O 已經成為制約系統性能的瓶頸。Java1.4 版本后推出的NIO 工具包,提供了非阻塞型I/O 的異步輸入輸出機制,為提高系統的性能提供了可實現的基礎機制。

NIO 包及工作原理

針對傳統I/O 工作模式的不足,NIO 工具包提出了基于Buffer(緩沖區)、Channel(通道)、Selector(選擇器)的新模式;Selector(選擇器)、可選擇的Channel(通道)和SelectionKey(選擇鍵)配合起來使用,可以實現并發的非阻塞型I/O 能力。

NIO 工具包的成員

Buffer(緩沖器)

Buffer 類是一個抽象類,它有7 個子類分別對應于七種基本的數據類型:ByteBuffer、CharBuffer、DoubleBuffer、FloatBuffer、IntBuffer、LongBuffer 和ShortBuffer。每一個Buffer對象相當于一個數據容器,可以把它看作內存中的一個大的數組,用來存儲和提取所有基本類型(boolean 型除外)的數據。Buffer 類的核心是一塊內存區,可以直接對其執行與內存有關的操作,利用操作系統特性和能力提高和改善Java 傳統I/O 的性能。

Channel(通道)

Channel 被認為是NIO 工具包的一大創新點,是(Buffer)緩沖器和I/O 服務之間的通道,具有雙向性,既可以讀入也可以寫出,可以更高效的傳遞數據。我們這里主要討ServerSocketChannel 和SocketChannel,它們都繼承了SelectableChannel,是可選擇的通道,分別可以工作在同步和異步兩種方式下(這里的可選擇不是指可以選擇兩種工作方式,而是指可以有選擇的注冊自己感興趣的事件)。當通道工作在同步方式時,它的功能和編程方法與傳統的ServerSocket、Socket 對象相似;當通道工作在異步工作方式時,進行輸入輸出處理不必等到輸入輸出完畢才返回,并且可以將其感興趣的(如:接受操作、連接操作、讀出操作、寫入操作)事件注冊到Selector 對象上,與Selector 對象協同工作可以更有效率的支持和管理并發的網絡套接字連接。

Selector(選擇器)和SelectionKey(選擇鍵)

各類 Buffer 是數據的容器對象;各類Channel 實現在各類Buffer 與各類I/O 服務間傳輸數據。Selector 是實現并發型非阻塞I/O 的核心,各種可選擇的通道將其感興趣的事件注冊到Selector 對象上,Selector 在一個循環中不斷輪循監視這各些注冊在其上的Socket 通道。SelectionKey 類則封裝了SelectableChannel 對象在Selector 中的注冊信息。當Selector 監測到在某個注冊的SelectableChannel 上發生了感興趣的事件時,自動激活產生一個SelectionKey對象,在這個對象中記錄了哪一個SelectableChannel 上發生了哪種事件,通過對被激活的SelectionKey 的分析,外界可以知道每個SelectableChannel 發生的具體事件類型,進行相應的處理。

NIO 工作原理

通過上面的討論,我們可以看出在并發型服務器程序中使用NIO,實際上是通過網絡事件驅動模型實現的。我們應用Select 機制,不用為每一個客戶端連接新啟線程處理,而是將其注冊到特定的Selector 對象上,這就可以在單線程中利用Selector 對象管理大量并發的網絡連接,更好的利用了系統資源;采用非阻塞I/O 的通信方式,不要求阻塞等待I/O 操作完成即可返回,從而減少了管理I/O 連接導致的系統開銷,大幅度提高了系統性能。

當有讀或寫等任何注冊的事件發生時,可以從Selector 中獲得相應的SelectionKey , 從SelectionKey 中可以找到發生的事件和該事件所發生的具體的SelectableChannel,以獲得客戶端發送過來的數據。由于在非阻塞網絡I/O 中采用了事件觸發機制,處理程序可以得到系統的主動通知,從而可以實現底層網絡I/O 無阻塞、流暢地讀寫,而不像在原來的阻塞模式下處理程序需要不斷循環等待。使用NIO,可以編寫出性能更好、更易擴展的并發型服務器程序。

并發型服務器程序的實現代碼

應用 NIO 工具包,基于非阻塞網絡I/O 設計的并發型服務器程序與以往基于阻塞I/O 的實現程序有很大不同,在使用非阻塞網絡I/O 的情況下,程序讀取數據和寫入數據的時機不是由程序員控制的,而是Selector 決定的。下面便給出基于非阻塞網絡I/O 的并發型服務器程序的核心代碼片段:

import java.io.*; //引入Java.io包  import java.net.*; //引入Java.net包  import java.nio.channels.*; //引入Java.nio.channels包  import java.util.*; //引入Java.util包  public class TestServer implements Runnable   {  /**   * 服務器Channel對象,負責接受用戶連接  */ private ServerSocketChannel server;  /**  * Selector對象,負責監控所有的連接到服務器的網絡事件的發生  */ private Selector selector;  /**  * 總的活動連接數  */ private int activeSockets;  /**  * 服務器Channel綁定的端口號  */ private int port ;  /**  *  * 構造函數  */ public TestServer()throws IOException  {  activeSockets=0;  port=9999;//初始化服務器Channel綁定的端口號為9999  selector= Selector.open();//初始化Selector對象  server=ServerSocketChannel.open();//初始化服務器Channel對象  ServerSocket socket=server.socket();//獲取服務器Channel對應的//ServerSocket對象  socket.bind(new InetSocketAddress(port));//把Socket綁定到監聽端口9999上  server.configureBlocking(false);//將服務器Channel設置為非阻塞模式  server.register(selector,SelectionKey.OP_ACCEPT);//將服務器Channel注冊到  Selector對象,并指出服務器Channel所感興趣的事件為可接受請求操作  }  public void run()  {  while(true)  {  try {  /**  *應用Select機制輪循是否有用戶感興趣的新的網絡事件發生,當沒有   * 新的網絡事件發生時,此方法會阻塞,直到有新的網絡事件發生為止  */ selector.select();   }  catch(IOException e)  {  continue;//當有異常發生時,繼續進行循環操作  }  /**  * 得到活動的網絡連接選擇鍵的集合  */ Set<SelectionKey> keys=selector.selectedKeys();  activeSockets=keys.size();//獲取活動連接的數目  if(activeSockets==0)  {  continue;//如果連接數為0,則繼續進行循環操作  }  /**   /**  * 應用For&mdash;Each循環遍歷整個選擇鍵集合  */ for(SelectionKey key :keys)  {  /**  * 如果關鍵字狀態是為可接受,則接受連接,注冊通道,以接受更多的*  事件,進行相關的服務器程序處理  */ if(key.isAcceptable())  {  doServerSocketEvent(key);  continue;  }  /**  * 如果關鍵字狀態為可讀,則說明Channel是一個客戶端的連接通道,  * 進行相應的讀取客戶端數據的操作  */ if(key.isReadable())  {  doClientReadEvent(key);  continue;  }  /**  * 如果關鍵字狀態為可寫,則也說明Channel是一個客戶端的連接通道,  * 進行相應的向客戶端寫數據的操作  */ if(key.isWritable())  {  doClinetWriteEvent(key);  continue;  }  }  }  }   /**  * 處理服務器事件操作  * @param key 服務器選擇鍵對象  */ private void doServerSocketEvent(SelectionKey key)  {  SocketChannel client=null;  try {  ServerSocketChannel server=(ServerSocketChannel)key.channel();  client=server.accept();  if(client==null)  {  return;  }  client.configureBlocking(false);//將客戶端Channel設置為非阻塞型  /**   /**  * 將客戶端Channel注冊到Selector對象上,并且指出客戶端Channel所感  * 興趣的事件為可讀和可寫  */ client.register(selector,SelectionKey.OP_READ|SelectionKey.OP_READ);  }catch(IOException e)  {  try {  client.close();   }catch(IOException e1){}  }  }  /**  * 進行向客戶端寫數據操作  * @param key 客戶端選擇鍵對象  */ private void doClinetWriteEvent(SelectionKey key)  {  代碼實現略;  }  /**  * 進行讀取客戶短數據操作  * @param key 客戶端選擇鍵對象  */ private void doClientReadEvent(SelectionKey key)  {  代碼實現略;  }  }

從上面對代碼可以看出,使用非阻塞性I/O進行并發型服務器程序設計分三個部分:1.向Selector對象注冊感興趣的事件;2.從Selector中獲取所感興趣的事件;3.根據不同的事件進行相應的處理。

“Java NIO開發的實例介紹”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

云梦县| 都江堰市| 隆林| 徐闻县| 香河县| 加查县| 石门县| 盐山县| 阳朔县| 星子县| 东乌珠穆沁旗| 玛沁县| 衢州市| 蒙自县| 阳泉市| 新化县| 安康市| 察哈| 灌云县| 武冈市| 万州区| 铜梁县| 贡觉县| 楚雄市| 苍梧县| 余江县| 安图县| 富裕县| 屏东县| 上思县| 望都县| 南投县| 云梦县| 肃宁县| 赤壁市| 灵寿县| 广元市| 涞源县| 益阳市| 镇原县| 吉林省|