熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> Java高級技術 >> 正文

Java I/O API之性能分析 (下)

2013-11-23 19:53:51  來源: Java高級技術 

  注冊與處理過程詳解
  接下來我們要分析Connection的register()方法前面我們總是說用Selector注冊的連接其實這是一種簡化的說法實際上用Selector注冊的是一個javaniochannelsSocketChannel對象但只針對特定的I/O操作注冊之後有一個javaniochannelsSelectionKey被返回這個選擇鍵可以通過attach()方法關聯到任意對象為了通過鍵獲得連接這裡把Connection對象關聯到鍵這樣我們就可以從Selector間接地獲得一個Connection
  
  public void register(Selector selector)
  throws IOException {
  key = socketChannelregister(selector SelectionKeyOP_READ);
  keyattach(this);
  }
  回過頭來看ConnectionSelectorselect()方法的返回值表示有多少連接已經做好了I/O操作的准備如果返回值是則返回否則調用selectedKeys()獲得鍵的集合(Set)從這些鍵獲得以前關聯的Connection對象然後調用其readRequest()或writeResponse()方法具體調用哪一個方法由連接被注冊為讀取操作還是寫入操作決定
  
  現在再來看Connection類Connection類代表著連接處理所有協議有關的細節在構造函數中通過參數傳入的SocketChannel被設置成非阻塞模式這對於服務器來說是很重要的另外構造函數還設置了一些默認值分配了緩沖區requestLineBuffer由於分配直接緩沖區代價稍高且這裡的每一個連接都用一個新的緩沖區因此這裡使用javanioByteBufferallocate()而不是ByteBufferallocateDirect()如果重用緩沖區直接緩沖區可能具有更高的效率
  
  public Connection(SocketChannel socketChannel)
  throws IOException {
  thissocketChannel = socketChannel;
  
  nfigureBlocking(false);
  requestLineBuffer = ByteBufferallocate();
  
  }
  
  完成所有初始化工作且SocketChannel做好了讀取准備之後ConnectionSelector調用了readRequest()方法利用socketChannelread(requestLineBuffer)方法把所有可用的數據讀入緩沖區如果不能讀取完整的行則返回發出調用的ConnectionSelector允許另一個連接進入處理過程反之如果成功地讀取了整個行接下來應該做的是象在Httpd中一樣解析請求如果當前的請求合法程序為請求目標文件創建一個javanioChannelsFileChannel並調用prepareForResponse()方法
  
  private void prepareForResponse() throws IOException {
  StringBuffer responseLine = new StringBuffer();
  
  responseLineBuffer = ByteBufferwrap(
  responseLinetoString()getBytes(ASCII)
  );
  keyinterestOps(SelectionKeyOP_WRITE);
  keyselector()wakeup();
  }
From:http://tw.wingwit.com/Article/program/Java/gj/201311/27638.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.