JAVA—咖啡館

          ——歡迎訪問rogerfan的博客,常來《JAVA——咖啡館》坐坐,喝杯濃香的咖啡,彼此探討一下JAVA技術,交流工作經驗,分享JAVA帶來的快樂!本網站部分轉載文章,如果有版權問題請與我聯系。

          BlogJava 首頁 新隨筆 聯系 聚合 管理
            447 Posts :: 145 Stories :: 368 Comments :: 0 Trackbacks

          Java NIO非堵塞應用通常適用用在I/O讀寫等方面,我們知道,系統運行的性能瓶頸通常在I/O讀寫,包括對端口和文件的操作上,過去,在打開一個I/O通道后,read()將一直等待在端口一邊讀取字節內容,如果沒有內容進來,read()也是傻傻的等,這會影響我們程序繼續做其他事情,那么改進做法就是開設線程,讓線程去等待,但是這樣做也是相當耗費資源的。

          Java NIO非堵塞技術實際是采取Reactor模式,或者說是Observer模式為我們監察I/O端口,如果有內容進來,會自動通知我們,這樣,我們就不必開啟多個線程死等,從外界看,實現了流暢的I/O讀寫,不堵塞了。

          Java NIO出現不只是一個技術性能的提高,你會發現網絡上到處在介紹它,因為它具有里程碑意義,從JDK1.4開始,Java開始提高性能相關的功能,從而使得Java在底層或者并行分布式計算等操作上已經可以和C或Perl等語言并駕齊驅。

          如果你至今還是在懷疑Java的性能,說明你的思想和觀念已經完全落伍了,Java一兩年就應該用新的名詞來定義。從JDK1.5開始又要提供關于線程、并發等新性能的支持,Java應用在游戲等適時領域方面的機會已經成熟,Java在穩定自己中間件地位后,開始蠶食傳統C的領域。

          本文主要簡單介紹NIO的基本原理,在下一篇文章中,將結合Reactor模式和著名線程大師Doug Lea的一篇文章深入討論。

          NIO主要原理和適用。

          NIO 有一個主要的類Selector,這個類似一個觀察者,只要我們把需要探知的socketchannel告訴Selector,我們接著做別的事情,當有事件發生時,他會通知我們,傳回一組SelectionKey,我們讀取這些Key,就會獲得我們剛剛注冊過的socketchannel,然后,我們從這個Channel中讀取數據,放心,包準能夠讀到,接著我們可以處理這些數據。

          Selector內部原理實際是在做一個對所注冊的channel的輪詢訪問,不斷的輪詢(目前就這一個算法),一旦輪詢到一個channel有所注冊的事情發生,比如數據來了,他就會站起來報告,交出一把鑰匙,讓我們通過這把鑰匙來讀取這個channel的內容。

          了解了這個基本原理,我們結合代碼看看使用,在使用上,也在分兩個方向,一個是線程處理,一個是用非線程,后者比較簡單,看下面代碼:

            1import java.io.*;
            2import java.nio.*;
            3import java.nio.channels.*;
            4import java.nio.channels.spi.*;
            5import java.net.*;
            6import java.util.*
            7/**
            8*
            9@author Administrator
           10@version
           11*/

           12public class NBTest {
           13
           14
           15  /** Creates new NBTest */
           16  public NBTest()
           17  {
           18  }

           19
           20  public void startServer() throws Exception
           21  {
           22  int channels = 0;
           23  int nKeys = 0;
           24  int currentSelector = 0;
           25
           26  //使用Selector
           27  Selector selector = Selector.open();
           28
           29  //建立Channel 并綁定到9000端口
           30  ServerSocketChannel ssc = ServerSocketChannel.open();
           31  InetSocketAddress address = new InetSocketAddress(InetAddress.getLocalHost(),9000); 
           32  ssc.socket().bind(address);
           33
           34  //使設定non-blocking的方式。
           35  ssc.configureBlocking(false);
           36
           37  //向Selector注冊Channel及我們有愛好的事件
           38  SelectionKey s = ssc.register(selector, SelectionKey.OP_ACCEPT);
           39  printKeyInfo(s);
           40
           41  while(true//不斷的輪詢
           42  {
           43    debug("NBTest: Starting select");
           44
           45    //Selector通過select方法通知我們我們感愛好的事件發生了。
           46    nKeys = selector.select();
           47    //假如有我們注冊的事情發生了,它的傳回值就會大于0
           48    if(nKeys > 0)
           49    {
           50      debug("NBTest: Number of keys after select operation: " +nKeys);
           51
           52      //Selector傳回一組SelectionKeys
           53      //我們從這些key中的channel()方法中取得我們剛剛注冊的channel。
           54      Set selectedKeys = selector.selectedKeys();
           55      Iterator i = selectedKeys.iterator();
           56      while(i.hasNext())
           57      {
           58         s = (SelectionKey) i.next();
           59         printKeyInfo(s);
           60         debug("NBTest: Nr Keys in selector: " +selector.keys().size());
           61
           62         //一個key被處理完成后,就都被從就緒要害字(ready keys)列表中除去
           63         i.remove();
           64         if(s.isAcceptable())
           65         {
           66           // 從channel()中取得我們剛剛注冊的channel。
           67           Socket socket = ((ServerSocketChannel) s.channel()).accept();
           68           SocketChannel sc = socket.getChannel();
           69
           70           sc.configureBlocking(false);
           71           sc.register(selector, SelectionKey.OP_READ SelectionKey.OP_WRITE);
           72                      System.out.println(++channels);
           73         }

           74         else
           75         {
           76           debug("NBTest: Channel not acceptable");
           77         }

           78      }

           79   }

           80   else
           81   {
           82      debug("NBTest: Select finished without any keys.");
           83   }

           84
           85  }

           86
           87}

           88
           89
           90private static void debug(String s)
           91{
           92  System.out.println(s);
           93}

           94
           95
           96private static void printKeyInfo(SelectionKey sk)
           97{
           98  String s = new String();
           99
          100  s = "Att: " + (sk.attachment() == null ? "no" : "yes");
          101  s += ", Read: " + sk.isReadable();
          102  s += ", Acpt: " + sk.isAcceptable();
          103  s += ", Cnct: " + sk.isConnectable();
          104  s += ", Wrt: " + sk.isWritable();
          105  s += ", Valid: " + sk.isValid();
          106  s += ", Ops: " + sk.interestOps();
          107  debug(s);
          108}

          109
          110
          111/**
          112@param args the command line arguments
          113*/

          114public static void main (String args[])
          115{
          116  NBTest nbTest = new NBTest();
          117  try
          118  {
          119    nbTest.startServer();
          120  }

          121    catch(Exception e)
          122  {
          123    e.printStackTrace();
          124  }

          125}

          126
          127}

          這是一個守候在端口9000的noblock server例子,如果我們編制一個客戶端程序,就可以對它進行互動操作,或者使用telnet 主機名 90000 可以鏈接上。

          通過仔細閱讀這個例程,相信你已經大致了解NIO的原理和使用方法,下一篇,我們將使用多線程來處理這些數據,再搭建一個自己的Reactor模式。

          posted on 2009-05-31 15:17 rogerfan 閱讀(689) 評論(0)  編輯  收藏 所屬分類: 【Java知識】
          主站蜘蛛池模板: 扬州市| 敦煌市| 苍梧县| 瓦房店市| 泉州市| 容城县| 饶平县| 东光县| 济阳县| 凤阳县| 巢湖市| 镇巴县| 宁化县| 玉林市| 东莞市| 昌宁县| 文登市| 新宁县| 陆丰市| 郁南县| 沂源县| 定南县| 偃师市| 烟台市| 林西县| 南陵县| 阜新市| 镇宁| 庆阳市| 乌鲁木齐县| 洮南市| 安泽县| 育儿| 铜川市| 海宁市| 万源市| 历史| 承德市| 宿迁市| 哈尔滨市| 昆明市|