Java AIO初探(非同步網路IO)

來源:互聯網
上載者:User

按照《Unix網路編程》的劃分,IO模型可以分為:阻塞IO、非阻塞IO、IO複用、訊號驅動IO和非同步IO,按照POSIX標準來劃分只分為兩類:同步IO和非同步IO。如何區分呢?首先一個IO操作其實分成了兩個步驟:發起IO請求和實際的IO操作,同步IO和非同步IO的區別就在於第二個步驟是否阻塞,如果實際的IO讀寫阻塞請求進程,那麼就是同步IO,因此阻塞IO、非阻塞IO、IO服用、訊號驅動IO都是同步IO,如果不阻塞,而是作業系統幫你做完IO操作再將結果返回給你,那麼就是非同步IO。阻塞IO和非阻塞IO的區別在於第一步,發起IO請求是否會被阻塞,如果阻塞直到完成那麼就是傳統的阻塞IO,如果不阻塞,那麼就是非阻塞IO。

Java nio 2.0的主要改進就是引入了非同步IO(包括檔案和網路),這裡主要介紹下非同步網路IO API的使用以及架構的設計,以TCP服務端為例。首先看下為了支援AIO引入的新的類和介面:

java.nio.channels.AsynchronousChannel

標記一個channel支援非同步IO操作。

java.nio.channels.AsynchronousServerSocketChannel

ServerSocket的aio版本,建立TCP服務端,綁定地址,監聽連接埠等。

java.nio.channels.AsynchronousSocketChannel

面向流的非同步socket channel,表示一個串連。

java.nio.channels.AsynchronousChannelGroup

非同步channel的分組管理,目的是為了資源共用。一個AsynchronousChannelGroup綁定一個線程池,這個線程池執行兩個任務:處理IO事件和派發CompletionHandler。AsynchronousServerSocketChannel建立的時候可以傳入一個 AsynchronousChannelGroup,那麼通過AsynchronousServerSocketChannel建立的 AsynchronousSocketChannel將同屬於一個組,共用資源。

java.nio.channels.CompletionHandler

非同步IO操作結果的回調介面,用於定義在IO操作完成後所作的回調工作。AIO的API允許兩種方式來處理非同步作業的結果:返回的Future模式或者註冊CompletionHandler,我更推薦用CompletionHandler的方式,這些handler的調用是由 AsynchronousChannelGroup的線程池派發的。顯然,線程池的大小是效能的關鍵因素。AsynchronousChannelGroup允許綁定不同的線程池,通過三個靜態方法來建立:

public static AsynchronousChannelGroup withFixedThreadPool(int nThreads,
                                                                ThreadFactory threadFactory)
         throws IOException
  public static AsynchronousChannelGroup withCachedThreadPool(ExecutorService executor,
                                                                 int initialSize)
  public static AsynchronousChannelGroup withThreadPool(ExecutorService executor)
         throws IOException

需要根據具體應用相應調整,從架構角度出發,需要暴露這樣的配置選項給使用者。

在介紹完了aio引入的TCP的主要介面和類之後,我們來設想下一個aio架構應該怎麼設計。參考非阻塞nio架構的設計,一般都是採用Reactor模式,Reacot負責事件的註冊、select、事件的派發;相應地,非同步IO有個Proactor模式,Proactor負責 CompletionHandler的派發,查看一個典型的IO寫操作的流程來看兩者的區別:

Reactor:  send(msg) -> 訊息佇列是否為空白,如果為空白  -> 向Reactor註冊OP_WRITE,然後返回 -> Reactor select -> 觸發Writable,通知使用者線程去處理 ->先登出Writable(很多人遇到的cpu 100%的問題就在於沒有登出),處理Writeable,如果沒有完全寫入,繼續註冊OP_WRITE。注意到,寫入的工作還是使用者線程在處理。

Proactor: send(msg) -> 訊息佇列是否為空白,如果為空白,發起read非同步呼叫,並註冊CompletionHandler,然後返回。 -> 作業系統負責將你的訊息寫入,並返回結果(寫入的位元組數)給Proactor -> Proactor派發CompletionHandler。可見,寫入的工作是作業系統在處理,無需使用者線程參與。事實上在aio的API 中,AsynchronousChannelGroup就扮演了Proactor的角色。

CompletionHandler有三個方法,分別對應於處理成功、失敗、被取消(通過返回的Future)情況下的回調處理:

public interface CompletionHandler<V,A> {
      void completed(V result, A attachment);
     void failed(Throwable exc, A attachment);

     void cancelled(A attachment);
}

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.