異步IO
下面摘子李剛的《瘋狂JAVA講義》
按照POSIX標準來劃分IO,分為同步IO和異步IO。對于IO操作分為兩步,1)程序發出IO請求。 2)完成實際的IO操作。
阻塞IO和非阻塞IO都是針對第一步來劃分的,如果發出IO請求會阻塞線程,就是阻塞IO,否則就是非阻塞IO。
同步IO和非同步IO是針對第二步來說的,如果實際IO操作是由操作系統完成,再返回給程序,就是異步IO。
如果實際的IO需要程序本身去執行,會阻塞線程,就是同步IO。
?
JAVA7的NIO.2提供了異步的channel, 從而使網絡Socket的異步通信成為可能。
使用異步IO通信只需要三步,
- 調用open靜態方法創建AsynchronousServerSocketChannel
- 調用AsynchronousServerSocketChannel的bind方法監聽指定IP和端口
- 調用AsynchronousServerSocketChannel的accept方法接受連接請求
下面是一個簡單例子,
服務器端
1 package aio; 2 3 import java.io.IOException; 4 import java.net.InetSocketAddress; 5 import java.nio.ByteBuffer; 6 import java.nio.channels.AsynchronousServerSocketChannel; 7 import java.nio.channels.AsynchronousSocketChannel; 8 import java.util.concurrent.ExecutionException; 9 import java.util.concurrent.Future; 10 11 public class Server { 12 private static final int PORT = 3002; 13 public static void main(String[] args) throws IOException, InterruptedException, ExecutionException { 14 try { 15 AsynchronousServerSocketChannel serverChannel = AsynchronousServerSocketChannel.open(); 16 serverChannel.bind(new InetSocketAddress(PORT)); 17 while (true) { 18 Future<AsynchronousSocketChannel> future = serverChannel.accept(); 19 //獲取連接成功之后的AsynchronousSocketChannel 20 AsynchronousSocketChannel socketChannel = future.get(); 21 socketChannel.write(ByteBuffer.wrap("你好,這是AIO世界".getBytes("utf-8"))).get(); 22 } 23 } catch(IOException e) { 24 e.printStackTrace(); 25 } 26 } 27 }
客戶端
1 package aio; 2 3 import java.io.IOException; 4 import java.net.InetSocketAddress; 5 import java.nio.ByteBuffer; 6 import java.nio.channels.AsynchronousSocketChannel; 7 import java.nio.charset.Charset; 8 import java.util.concurrent.ExecutionException; 9 10 public class Client { 11 private static final int PORT = 3002; 12 public static void main(String[] args) throws IOException, InterruptedException, ExecutionException { 13 ByteBuffer buff = ByteBuffer.allocate(1024); 14 Charset utf = Charset.forName("utf-8"); 15 try { 16 AsynchronousSocketChannel clientChannel = AsynchronousSocketChannel.open(); 17 clientChannel.connect(new InetSocketAddress("127.0.0.1",PORT)).get(); 18 buff.clear(); 19 clientChannel.read(buff).get(); 20 buff.flip(); 21 String content = utf.decode(buff).toString(); 22 System.out.println("服務器信息:"+content); 23 } catch (IOException ex) { 24 ex.printStackTrace(); 25 } 26 } 27 }
執行結果,使用一個服務器端和兩個客戶端測試,
?