Java7之前只支持BIO颂翼、NIO矫废,但在Java 7 時添加了Java AIO有勾,Java AIO基于epoll模式來模擬實現(xiàn)(Linux 2.6)
阻塞/非阻塞 -- 同步/異步
系統(tǒng)I/O 可分為阻塞型修肠、非阻塞同步型以及非阻塞異步型秫逝。
阻塞型I/O意味著控制權只到調(diào)用操作結束了才會回到調(diào)用者手里恕出。結果調(diào)用者被阻塞了, 這段時間了做不了任何其它事情.。
非阻塞同步是會立即返回控制權給調(diào)用者的违帆。調(diào)用者不需要等等浙巫,它從調(diào)用的函數(shù)獲取兩種結果:要么此次調(diào)用成功進行了;要么系統(tǒng)返回錯誤標識告訴調(diào)用者當前資源不可用,你再等等或者再試度看吧前方。
在非阻塞異步調(diào)用中狈醉,稍有不同。調(diào)用函數(shù)在立即返回時惠险,還告訴調(diào)用者苗傅,這次請求已經(jīng)開始了。系統(tǒng)會使用另外的資源或者線程來完成這次調(diào)用操作班巩,并在完成的時候知會調(diào)用者(比如通過回調(diào)函數(shù))渣慕。
NIO與AIO比較
NIO監(jiān)聽的是什么事件準備好了嘶炭,然后通知當前線程去處理,在通知返回之前需要等待逊桦,并且需要Selector配合通知線程眨猎;AIO監(jiān)聽的什么事件已經(jīng)完成了,然后執(zhí)行對應的處理函數(shù)(系統(tǒng)來開辟一個線程來完成)强经,執(zhí)行完成會通知關心這個事件完成的線程睡陪,在沒有通知時當前線程可以先做自己的事情,當空閑下來的時候檢查一下通知回來的信息匿情,在獲取通知結果時會阻塞兰迫,但是可以設置超時時間,當一段時間沒有還沒有結果炬称,則繼續(xù)干別的事情汁果。
AIO并不比BIO的IO讀寫更快,只是關注事件的階段不一樣玲躯,系統(tǒng)通知線程的方式不一樣据德,但是AIO比NIO簡化了代碼編寫的復雜度,并且效率更高跷车、更高伸縮性棘利。
由于NIO的讀寫過程依然在應用線程里完成,所以對于那些讀寫過程時間長的朽缴,NIO就不太適合赡译。而AIO的讀寫過程完成后才被通知,所以AIO能夠勝任那些重量級不铆,讀寫過程長的任務。
AIO異步的幾個重要的方法
AIO 的異步操作總體上是基于系統(tǒng)調(diào)用Handler以及返回Future異步結果來實現(xiàn)的裹唆。
- AsynchronousFileChannel(由于FileChannel只讀權限誓斥,所以沒有write方法)
程序調(diào)用此方法后立即返回,并由系統(tǒng)將接收的數(shù)據(jù)讀入指定的ByteBuffer中许帐,在讀取完成之后執(zhí)行用戶指定的處理函數(shù)進行處理劳坑,可以綁定一個對象在處理函數(shù)上,以便IO處理函數(shù)可以和用戶程序的信息通信成畦。
程序調(diào)用此方法后立即返回一個Future對象距芬,然后由系統(tǒng)默默地將接收的數(shù)據(jù)讀入指定的ByteBuffer中,用戶通過超時獲取結果Future.get(timeout)循帐,當沒有結果時在超時時間結束時可以干其他的事情框仔,在空閑的時候在進行判斷一下,當讀取完成拄养,系統(tǒng)會在get方法還沒有超時返回离斩,用戶就可以獲得讀取了多少個字節(jié)(get方法讀到的字節(jié)數(shù),返回-1表示文件流結束,超時和沒有字節(jié)可讀都返回0跛梗,超時可以結合Future.isDone()方法判斷任務是否完成)
- AsynchronousByteChannel
read方法同上
write方法:
程序調(diào)用此方法后立即返回寻馏,并由系統(tǒng)將指定的ByteBuffer寫入到此通道中,在寫入完成之后執(zhí)行用戶指定的處理函數(shù)進行處理核偿,可以綁定一個對象在處理函數(shù)上诚欠,以便IO處理函數(shù)可以和用戶程序的信息通信。
程序調(diào)用此方法后立即返回一個Future對象漾岳,并由系統(tǒng)將指定的ByteBuffer寫入到此通道中轰绵,用戶通過超時獲取結果Future.get(timeout),當沒有結果時在超時時間結束時可以干其他的事情蝗羊,在空閑的時候在進行判斷一下藏澳,當寫入完成,系統(tǒng)會在get方法還沒有超時返回耀找,用戶就可以獲得寫入了多少個字節(jié)(超時可以結合Future.isDone()方法判斷任務是否完成翔悠。
注意要保證ByteBuffer的線程安全,否則將發(fā)生異常野芒。
- AsynchronousSocketChannel
Socket通道還有connect以及open方法
open方法開啟一個異步通道蓄愁,不同于FileChannel(從流文件中獲取)狞悲,socket需要顯示調(diào)用open方法撮抓,開啟通道。
異步連接
異步讀
異步寫
- AsynchronousServerSocketChannel
ServerSocketChannel沒有讀寫操作摇锋,但是有open丹拯,bind以及異步accept方法
open方法
bind方法
異步accept方法
- CompletionHandler處理函數(shù)接口
客戶端程序
服務端程序
測試結果
客戶端
服務端
源碼地址
https://github.com/zhanglbjames/exercises/blob/master/src/main/java/test/TestProactorClient.java
https://github.com/zhanglbjames/exercises/blob/master/src/main/java/test/TestProactorServer.java