JDK7已經release一段時間了,有個重要的新特性是AIO。
今天趁閒暇,簡單體驗了下,簡單分享以下:
關於AIO的概念理解
關於AIO的概念,僅談談我的的一點理解。可能不到位,請你們指出。
Io的兩個重要步驟:發起IO請求,和實際的IO操做。在unix網絡編程的定義裏異步和非異步概念的區別就是實際的IO操做是否阻塞。若是不是就是異步,若是是就是同步。
而阻塞和非阻塞的區別在於發起IO請求的時候是否會阻塞,若是會就是阻塞,不會就是非阻塞。
本人理解能力有限,想了個例子來輔助本身理解:
小明想要買一本<深刻java虛擬機>的書,如下幾個場景能夠來理解這幾種io模式:
1. 若是小明天天都去書店問售貨員說有沒有這本書,若是沒有就回去繼續等待,等下次再過來文。(阻塞)
2. 若是小明告訴售貨員想買一本<深刻java虛擬機>的書,那麼就在家裏等着作其餘事情去了,若是書到了售貨員就通知小明,小明再本身過去取。
3. 若是小明告售貨員想買一本<深刻java虛擬機>的書,而後告訴售貨員到了幫他送到某某地方去,就作其餘事情去了。小明就無論了,等書到了,售貨員就幫他送到那個地方了。
售貨員能夠認爲是操做系統的一個服務,而小明是一個用戶進程。不知道是否有誤,若是有誤請你們拍磚指出,謝謝。
能夠看出2,3的效率明顯要比1高。可是1最簡單,而2,3須要一些協做。充分證實了團隊合做的力量。
JDK7AIO初體驗
AsynchronousChannel:支持異步通道,包括服務端AsynchronousServerSocketChannel和普通AsynchronousSocketChannel等實現。
CompletionHandler:用戶處理器。定義了一個用戶處理就緒事件的接口,由用戶本身實現,異步io的數據就緒後回調該處理器消費或處理數據。
AsynchronousChannelGroup:一個用於資源共享的異步通道集合。處理IO事件和分配給CompletionHandler。(具體這塊還沒細看代碼,後續再分析這塊)
以一個簡單監聽服務端爲例,基本過程是:
1. 啓動一個服務端通道
2. 定義一個事件處理器,用戶事件完成的時候處理,如消費數據。
3. 向系統註冊一個感興趣的事件,如接受數據,並把事件完成的處理器傳遞給系統。
4. 都已經交待完畢,能夠只管繼續作本身的事情了,操做系統在完成事件後經過其餘的線程會自動調用處理器完成事件處理。
如下用一個例子來簡單實現,一個服務端和客戶端。服務端監聽客戶端的消息,並打印出來。
AIOServer.javahtml
Java代碼
- package io.aio;
-
- import java.io.IOException;
- import java.net.InetSocketAddress;
- import java.nio.ByteBuffer;
- import java.nio.channels.AsynchronousServerSocketChannel;
- import java.nio.channels.AsynchronousSocketChannel;
- import java.nio.channels.CompletionHandler;
- import java.util.concurrent.ExecutionException;
- import java.util.concurrent.Future;
- import java.util.concurrent.TimeUnit;
- import java.util.concurrent.TimeoutException;
-
-
- public class AIOServer {
- public final static int PORT = 9888;
- private AsynchronousServerSocketChannel server;
-
- public AIOServer() throws IOException {
- server = AsynchronousServerSocketChannel.open().bind(
- new InetSocketAddress(PORT));
- }
-
- public void startWithFuture() throws InterruptedException,
- ExecutionException, TimeoutException {
- System.out.println("Server listen on " + PORT);
- Future<AsynchronousSocketChannel> future = server.accept();
- AsynchronousSocketChannel socket = future.get();
- ByteBuffer readBuf = ByteBuffer.allocate(1024);
- readBuf.clear();
- socket.read(readBuf).get(100, TimeUnit.SECONDS);
- readBuf.flip();
- System.out.printf("received message:" + new String(readBuf.array()));
- System.out.println(Thread.currentThread().getName());
-
- }
-
- public void startWithCompletionHandler() throws InterruptedException,
- ExecutionException, TimeoutException {
- System.out.println("Server listen on " + PORT);
- //註冊事件和事件完成後的處理器
- server.accept(null,
- new CompletionHandler<AsynchronousSocketChannel, Object>() {
- final ByteBuffer buffer = ByteBuffer.allocate(1024);
-
- public void completed(AsynchronousSocketChannel result,
- Object attachment) {
- System.out.println(Thread.currentThread().getName());
- System.out.println("start");
- try {
- buffer.clear();
- result.read(buffer).get(100, TimeUnit.SECONDS);
- buffer.flip();
- System.out.println("received message: "
- + new String(buffer.array()));
- } catch (InterruptedException | ExecutionException e) {
- System.out.println(e.toString());
- } catch (TimeoutException e) {
- e.printStackTrace();
- } finally {
-
- try {
- result.close();
- server.accept(null, this);
- } catch (Exception e) {
- System.out.println(e.toString());
- }
- }
-
- System.out.println("end");
- }
-
- @Override
- public void failed(Throwable exc, Object attachment) {
- System.out.println("failed: " + exc);
- }
- });
- // 主線程繼續本身的行爲
- while (true) {
- System.out.println("main thread");
- Thread.sleep(1000);
- }
-
- }
-
- public static void main(String args[]) throws Exception {
- new AIOServer().startWithCompletionHandler();
- }
- }
AIOClient.javajava
Java代碼
- package io.aio;
-
- import java.net.InetSocketAddress;
- import java.nio.ByteBuffer;
- import java.nio.channels.AsynchronousSocketChannel;
-
- public class AIOClient {
-
- public static void main(String... args) throws Exception {
- AsynchronousSocketChannel client = AsynchronousSocketChannel.open();
- client.connect(new InetSocketAddress("localhost", 9888));
- client.write(ByteBuffer.wrap("test".getBytes())).get();
- }
- }
服務端寫了兩種處理實現方式,startWithCompletionHandler是經過Handler來處理,startWithFuture是經過Future方式來處理。startWithCompletionHandler方法裏能夠看到調用accepte()完成異步註冊後,線程就能夠繼續本身的處理了,徹底不被這個io所中斷。編程
從以上來看AIO的代碼簡單了不少,至少比NIO的代碼實現簡單不少。網絡