JDK7 AIO介绍
1. JDK7 AIO初體驗
JDK7已經release一段時間了,有個重要的新特性是AIO。今天趁閑暇,簡單體驗了下,簡單分享如下:
2. 關于AIO的概念理解
關于AIO的概念,僅談談個人的一點理解。可能不到位,請大家指出。
Io的兩個重要步驟:發起IO請求,和實際的IO操作。在unix網絡編程的定義里異步和非異步概念的區別就是實際的IO操作是否阻塞。如果不是就是異步,如果是就是同步。
而阻塞和非阻塞的區別在于發起IO請求的時候是否會阻塞,如果會就是阻塞,不會就是非阻塞。
本人理解能力有限,想了個例子來輔助自己理解:
小明想要買一本<深入java虛擬機>的書,以下幾個場景可以來理解這幾種io模式:
售貨員可以認為是操作系統的一個服務,而小明是一個用戶進程。不知道是否有誤,如果有誤請大家拍磚指出,謝謝。
可以看出2,3的效率明顯要比1高。但是1最簡單,而2,3需要一些協作。充分證明了團隊合作的力量。
3. JDK7 AIO初體驗
AsynchronousChannel:支持異步通道,包括服務端AsynchronousServerSocketChannel和普通AsynchronousSocketChannel等實現。
CompletionHandler:用戶處理器。定義了一個用戶處理就緒事件的接口,由用戶自己實現,異步io的數據就緒后回調該處理器消費或處理數據。
AsynchronousChannelGroup:一個用于資源共享的異步通道集合。處理IO事件和分配給CompletionHandler。(具體這塊還沒細看代碼,后續再分析這塊)
以一個簡單監聽服務端為例,基本過程是:
以下用一個例子來簡單實現,一個服務端和客戶端。服務端監聽客戶端的消息,并打印出來
AIOServer.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;/*** * @author noname*/ 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");}@Overridepublic 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.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的代碼實現簡單很多。
4. AIO和NIO性能哪個好
Java NIO : 同步非阻塞,服務器實現模式為一個請求一個線程,即客戶端發送的連接請求都會注冊到多路復用器上,多路復用器輪詢到連接有I/O請求時才啟動一個線程進行處理。
Java AIO(NIO.2) : 異步非阻塞,服務器實現模式為一個有效請求一個線程,客戶端的I/O請求都是由OS先完成了再通知服務器應用去啟動線程進行處理,
NIO方式適用于連接數目多且連接比較短(輕操作)的架構,比如聊天服務器,并發局限于應用中,編程比較復雜,JDK1.4開始支持。
AIO方式使用于連接數目多且連接比較長(重操作)的架構,比如相冊服務器,充分調用OS參與并發操作,編程比較復雜,JDK7開始支持
I/O屬于底層操作,需要操作系統支持,并發也需要操作系統的支持,所以性能方面不同操作系統差異會比較明顯。另外NIO的非阻塞,需要一直輪詢,也是一個比較耗資源的。所以出現AIO
5. 使用J2SE進行服務器架構技術選型的變遷
雖然現在對大多數程序員來講,基本不會再有使用Java開發一個服務器這樣的任務,但是,這方面的技術研究一下,對自己的技術提高還是非常有幫助的。說不定啥時候能派上用場。
使用Java(J2SE)來設計服務器產品(不使用開源或其他已有產品)的架構,隨著Java的不斷發展,這幾年也發生了很大變化。在JDK1.4之前,使用Java構建服務器應用本身就很少,所以這里也就不提了,我們從JDK1.4開始說。
階段1:一個連接一個線程
階段2:服務器端采用了線程池
階段1和階段2雖然簡單,但是很實用,在很多場景下仍然是第一選擇。而且編程模型業內非常簡單。
階段3:采用非阻塞IO,多路復用技術,又有兩種不同的方式
這種方式很重要的一點就是在IO事件發生時得到通知,由程序進行處理。
NIO給編程帶來了很大的復雜度,使用NIO開發非常不容易,也很容易犯錯誤,所以,采用別人的框架是一個簡單而自然的選擇,采用grizzly和mina都很不錯,對通用的場景都能滿足要求。這里提醒一下,不管mina和grizzly,都有一些你不想用的特性,干擾你想用的功能,需要小心對待,最好自己也能處理mina和grizzly的bug,改進這些框架的功能。
再有,給予NIO來開發SSL也很復雜。
階段4:使用AIO技術
AIO最大的特性就是事前先設置好事件的回調函數,事件發生時自動調用回調。而且,得到的通知是“IO操作完成”,而不是NIO的“IO操作即將開始”。
使用AIO,在上層開發SSL也也很麻煩。
6. 原文鏈接
- http://www.iteye.com/topic/1113611
- http://windshome.iteye.com/blog/1837558
- https://zhidao.baidu.com/question/873378431735591372.html
總結
以上是生活随笔為你收集整理的JDK7 AIO介绍的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java NIO 系列教程
- 下一篇: NIO和AIO