java aio_java中的AIO
簡介
jdk7中新增了一些與文件(網絡)I/O相關的一些api。這些API被稱為NIO.2,或稱為AIO(Asynchronous I/O)。AIO最大的一個特性就是異步能力,這種能力對socket與文件I/O都起作用。AIO其實是一種在讀寫操作結束之前允許進行其他操作的I/O處理。AIO是對JDK1.4中提出的同步非阻塞I/O(NIO)的進一步增強。
關于NIO,之前的一篇文章可以看看:java中的NIO
jdk7主要增加了三個新的異步通道:
AsynchronousFileChannel: 用于文件異步讀寫;
AsynchronousSocketChannel: 客戶端異步socket;
AsynchronousServerSocketChannel: 服務器異步socket。
因為AIO的實施需充分調用OS參與,IO需要操作系統支持、并發也同樣需要操作系統的支持,所以性能方面不同操作系統差異會比較明顯。
前提概念
在具體看AIO之前,我們需要知道一些必要的前提概念。
Unix中的I/O模型
Unix定義了五種I/O模型
阻塞I/O
非阻塞I/O
I/O復用(select、poll、linux 2.6種改進的epoll)
信號驅動IO(SIGIO)
異步I/O(POSIX的aio_系列函數)
一個戲謔的例子:
如果你想吃一份宮保雞丁蓋飯:
同步阻塞:你到飯館點餐,然后在那等著,還要一邊喊:好了沒啊!
同步非阻塞:在飯館點完餐,就去遛狗了。不過溜一會兒,就回飯館喊一聲:好了沒啊!
異步阻塞:遛狗的時候,接到飯館電話,說飯做好了,讓您親自去拿。
異步非阻塞:飯館打電話說,我們知道您的位置,一會給你送過來,安心遛狗就可以了。
詳情參見文章末尾的他山之石-Unix下五種IO模型。
Reactor與Proactor
兩種IO多路復用方案:Reactor and Proactor。
Reactor模式是基于同步I/O的,而Proactor模式是和異步I/O相關的。
reactor:能收了你跟俺說一聲。proactor: 你給我收十個字節,收好了跟俺說一聲。
詳情參見文章末尾的他山之石-IO設計模式:Reactor和Proactor對比。
異步的處理
異步無非是通知系統做一件事情。然后忘掉它,自己做其他事情去了。很多時候系統做完某一件事情后需要一些后續的操作。怎么辦?這時候就是告訴異步調用如何做后續處理。通常有兩種方式:
將來式: 當你希望主線程發起異步調用,并輪詢等待結果的時候使用將來式;
回調式: 常說的異步回調就是它。
以文件讀取為例
將來式
將來式用現有的Java.util.concurrent技術聲明一個Future,用來保存異步操作的處理結果。通常用Future get()方法(帶或不帶超時參數)在異步IO操作完成時獲取其結果。
AsynchronousFileChannel會關聯線程池,它的任務是接收IO處理事件,并分發給負責處理通道中IO操作結果的結果處理器。跟通道中發起的IO操作關聯的結果處理器確保是由線程池中的某個線程產生。
將來式例子:
Path path = Paths.get("/data/code/github/java_practice/src/main/resources/1log4j.properties");
AsynchronousFileChannel channel = AsynchronousFileChannel.open(path);
ByteBuffer buffer = ByteBuffer.allocate(1024);
Future future = channel.read(buffer,0);
// while (!future.isDone()){
// System.out.println("I'm idle");
// }
Integer readNumber = future.get();
buffer.flip();
CharBuffer charBuffer = CharBuffer.allocate(1024);
CharsetDecoder decoder = Charset.defaultCharset().newDecoder();
decoder.decode(buffer,charBuffer,false);
charBuffer.flip();
String data = new String(charBuffer.array(),0, charBuffer.limit());
System.out.println("read number:" + readNumber);
System.out.println(data);
回調式
回調式所采用的事件處理技術類似于Swing UI編程采用的機制?;舅枷胧侵骶€程會派一個偵查員CompletionHandler到獨立的線程中執行IO操作。這個偵查員將帶著IO的操作的結果返回到主線程中,這個結果會觸發它自己的completed或failed方法(要重寫這兩個方法)。在異步IO活動結束后,接口java.nio.channels.CompletionHandler會被調用,其中V是結果類型,A是提供結果的附著對象。此時必須已經有了該接口completed(V,A)和failed(V,A)方法的實現,你的程序才能知道異步IO操作成功或失敗時該如何處理。
回調式例子:
Path path = Paths.get("/data/code/github/java_practice/src/main/resources/1log4j.properties");
AsynchronousFileChannel channel = AsynchronousFileChannel.open(path);
ByteBuffer buffer = ByteBuffer.allocate(1024);
channel.read(buffer, 0, buffer, new CompletionHandler() {
@Override
public void completed(Integer result, ByteBuffer attachment) {
System.out.println(Thread.currentThread().getName() + " read success!");
}
@Override
public void failed(Throwable exc, ByteBuffer attachment) {
System.out.println("read error");
}
});
while (true){
System.out.println(Thread.currentThread().getName() + " sleep");
Thread.sleep(1000);
}
異步socket client操作
AsynchronousSocketChannel channel = AsynchronousSocketChannel.open();
channel.connect(new InetSocketAddress("127.0.0.1",8888)).get();
ByteBuffer buffer = ByteBuffer.wrap("中文,你好".getBytes());
Future future = channel.write(buffer);
future.get();
System.out.println("send ok");
異步socket server操作
final AsynchronousServerSocketChannel channel = AsynchronousServerSocketChannel
.open()
.bind(new InetSocketAddress("0.0.0.0",8888));
channel.accept(null, new CompletionHandler() {
@Override
public void completed(final AsynchronousSocketChannel client, Void attachment) {
channel.accept(null, this);
ByteBuffer buffer = ByteBuffer.allocate(1024);
client.read(buffer, buffer, new CompletionHandler() {
@Override
public void completed(Integer result_num, ByteBuffer attachment) {
attachment.flip();
CharBuffer charBuffer = CharBuffer.allocate(1024);
CharsetDecoder decoder = Charset.defaultCharset().newDecoder();
decoder.decode(attachment,charBuffer,false);
charBuffer.flip();
String data = new String(charBuffer.array(),0, charBuffer.limit());
System.out.println("read data:" + data);
try{
client.close();
}catch (Exception e){}
}
@Override
public void failed(Throwable exc, ByteBuffer attachment) {
System.out.println("read error");
}
});
}
@Override
public void failed(Throwable exc, Void attachment) {
System.out.println("accept error");
}
});
while (true){
Thread.sleep(1000);
}
他山之石
總結
以上是生活随笔為你收集整理的java aio_java中的AIO的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java远程方法调用(rmi)--好_R
- 下一篇: java实现计分_非常实用的java自动