IO 多路複用實現的是同步IO 方式,具體來講,就是對於異步方式,只有AIO 。這裏指的就是在Java 中。
1 AIO 概覽
對於Aio 技術的實現,具體的實現可以在使用的過程中慢慢摸索,但是要先有一個總體概念。
1.1 AIO 底層實現過程
異步IO則採用“訂閱-通知”模式:即應用程序向操作系統註冊IO監聽,然後繼續做自己的事情。當操作系統發生IO事件,並且準備好數據後,在主動通知應用程序,觸發相應的函數。
JAVA AIO框架在windows下使用
windows IOCP
技術,在Linux 2.6 內核之後 下使用epoll多路複用
IO技術模擬異步IO
.1
- 實現 IOCP 技術部分
Java 中異步 I/O 和 IOCP
- 其實,JDK 中的 IOCP 的實現與前文中所描述的實現思想基本相同,唯一的區別是 JDK 中封裝了相關的內部實現。
- Iocp 類:該類使用默認的訪問修飾符,因此只能被同包(sun.nio.ch)的其他類訪問。同時,創建 IOCP 端口的 createIoCompletionPort 方法也被封裝在 Iocp 類的構造函數中,套接字的關聯也不再需要調用 createIoCompletionPort 而是直接調用 Iocp 類的 associate 方法。
- Iocp.CompletionStatus 類:Iocp 的內部類 CompletionStatus 用於存取完成端口的狀態信息。
- Iocp.EventHandlerTask 類:Iocp 的內部類 EventHandlerTask 用來將 I/O 操作的 Handle 關聯到完成端口,循環的獲取完成端口的狀態,根據操作系統返回的完成端口狀態從任務隊列中提取下一個要執行的任務並調用執行。
- Iocp 的調用類:sun.nio.ch 包中的
WindowsAsynchronousSocketChannelImpl、WindowsAsynchronousServerSocketChannelImpl 和 WindowsAsynchronousFileChannelImpl
等類使用了Iocp 類
的相關方法,達到多併發量時的高性能 I/O 訪問。- Native 方法:
Iocp 類中的許多內部方法
都是通過調用 JNI 方法
實現的。2
- 調用epoll 模擬異步。
在linux上,AIO的實現是通過epoll來完成的,看JDK源碼,可以發現,實現源碼是:
UnixAsynchronousSocketChannelImpl
看實現接口:implements Port.PollableChannel
1.2 java AIO 現狀
- 結論
1. Doing socket I/O efficiently has been solved with kqueue, epoll, IO completion ports and the likes. Doing asynchronous file I/O is sort of a late comer (apart from windows’ overlapped I/O and solaris early support for posix AIO).
2. 用處:The main purpose of AIO is hence to solve the problem of asynchronous disk I/O. This is most likely why Mac OS X only supports AIO for regular files, and not sockets (since kqueue does that so much better anyway).
Disk write I/O is already buffered and diskread I/O can be prefetched into buffer using functions like posix_fadvise. That leaves direct, unbuffered disk I/O as the only useful purpose for AIO.
I believe it's fairly common among OSes to not support posix AIO for any fd, but restrict it to regular files.
3
這裏也就解釋
- 爲什麼java 中的AIO 在linux中,沒有使用底層的AIO來實現。而是模擬epoll 多路複用修改而成的
- Netty 爲什麼沒有關於對於AIO的實現,網上講Netty 嘗試來實現AIO ,最後放棄的原因