June 22, 2004

Asynchronous IO for JAVA

原本JDK1.5要加進asynchonous io這個feature的
後來就不見了..有點小失望
不過今天在TTS看到IBM的alphawork有一個在java平台上實作aio的project
馬上就抓回來觀賞一下..^^

在談論這個project之前 先介紹一下什麼是aio
在最早期的java都是使用blocking io
也就是每個read/write都是blocking operation
這些method都會等到真的讀到或是寫到才會return
blocking io的好處是程式好寫 邏輯也比較直覺
但是缺點是如果有較多個連線時
必須要使用multithread的架構
但是thread一多就會使得整體效能變差

在jdk1.4時 多了一個java.nio這個package
稱之為new io
裡面題供一個feature是non-blocking IO
在這種模式中... 呼叫read/write都保證不會被block
也就是有資料可以讀.. 沒有就不讀
絕對不會卡住
但是直接使用會造成busy loop
所通常non-blocking io會搭配multiplexing io的使用
也就是select這東西
首先每個channel必須要跟selector註冊自己感興趣的operation
(如read/write/connect/accept)
之後selector做select時
他會觀察是不是有任何一個channel他所感興趣的operation已經available了
如果有任何一個available時
這個select就會return
之後 我們就可以根據SelectionKey找到該channel
並且做對應的operation
這種編程模式可以使用single thread就可完成
當然就不會有blocking io的太多thread的缺點
但是相對的就不好寫 邏輯很不容易懂
因此還有另一種io的編程模式asynchronous io的出現

aio這種寫作思維是我乾脆就告訴系統我要做哪一個operation(譬如read)
然後系統做好之後再通知我就好
這種委託系統幫你做某個operation就是一種asynchronous的概念
而要知道operation是否完成有三種方法
1. Blocking
站著等別人幫你做完
2. Poll
問說好了沒... 沒有的話就回去做自己的事情
等再過一段時間再去問好了沒...
3. Call-back
你好了再告訴我

在blocking或是non-blocking的模式中
所做的operation都是synchrnous的
也就是return就代表這個operation完成
只是不一定會讀到資料而已
而在aio中
operation return時代表我已經委託這個工作給別人
但不代表這個operation已經完成


alphawork這個專案叫做aio4j
看了一下感覺很不錯
他是使用POSA2:Wrapper Facade這個pattern
也就是底層是使用各個OS的aio實作
上層是用一個共同的API來包裝底層時做細節
所以兼具了跨平台跟效能特性
它提供的OS有WIN32 Linux32 AIX32 AIX64
使用的時候必須把對應平台的library放到正確的位置
使用上也不難
以下是一個例子

//打開一個async socket
AsyncSocketChannel myChannel = AsyncSocketChannel.open();
//非同步的建立連線  回傳一個Future (可以視為一個未來的結果)
IConnectionFuture connectionFuture = 
    myChannel.connect(new InetSocketAddress(serverhost,serverport));
//等到連線結束 (blocking wait)
connectionFuture.complete();
//讀一筆資料
IAsyncFuture readFuture = myChannel.read(byteBuffer);
//如果讀完則這個call會return, 並且回傳有多少個byte被read
int bytesRead = readFuture.getByteCount();

感覺上好像跟傳統的io沒什麼兩樣
那是因為我們都是用blocking的例子
aio4j也提供了poll跟Call-back

至於Future的概念
在aio4j中所有的operation都是會回傳一個future
這個叫做Future Pattern..
我們必須透過這個future去取得這個operation的結果
不管是blocking, poll, 或是設一個call-back listener

另外aio4j跟nio一樣
提供了scatter跟gatter io的概念
細節就不多講
以下是一個範例

AsyncSocketChannelHelper myHelper = AsyncSocketChannelHelper(myChannel);
IAsyncMultiFuture readFuture = myHelper.read(byteBufsArray);
...

Posted by popcorny at 05:25 PM | Comments (9) | TrackBack