异步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 }
执行结果,使用一个服务器端和两个客户端测试,