异步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 Futurefuture = serverChannel.accept();19 //获取连接成功之后的AsynchronousSocketChannel20 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 }
执行结果,使用一个服务器端和两个客户端测试,