JDK7已经release一段时间了,有个重要的新特性是AIO。
今天趁闲暇,简单体验了下,简单分享以下:
关于AIO的概念理解
关于AIO的概念,仅谈谈我的的一点理解。可能不到位,请你们指出。
Io的两个重要步骤:发起IO请求,和实际的IO操做。在unix网络编程的定义里异步和非异步概念的区别就是实际的IO操做是否阻塞。若是不是就是异步,若是是就是同步。
而阻塞和非阻塞的区别在于发起IO请求的时候是否会阻塞,若是会就是阻塞,不会就是非阻塞。
本人理解能力有限,想了个例子来辅助本身理解:
小明想要买一本<深刻java虚拟机>的书,如下几个场景能够来理解这几种io模式:
1. 若是小明天天都去书店问售货员说有没有这本书,若是没有就回去继续等待,等下次再过来文。(阻塞)
2. 若是小明告诉售货员想买一本<深刻java虚拟机>的书,那么就在家里等着作其余事情去了,若是书到了售货员就通知小明,小明再本身过去取。
3. 若是小明告售货员想买一本<深刻java虚拟机>的书,而后告诉售货员到了帮他送到某某地方去,就作其余事情去了。小明就无论了,等书到了,售货员就帮他送到那个地方了。
售货员能够认为是操做系统的一个服务,而小明是一个用户进程。不知道是否有误,若是有误请你们拍砖指出,谢谢。
能够看出2,3的效率明显要比1高。可是1最简单,而2,3须要一些协做。充分证实了团队合做的力量。
JDK7AIO初体验
AsynchronousChannel:支持异步通道,包括服务端AsynchronousServerSocketChannel和普通AsynchronousSocketChannel等实现。
CompletionHandler:用户处理器。定义了一个用户处理就绪事件的接口,由用户本身实现,异步io的数据就绪后回调该处理器消费或处理数据。
AsynchronousChannelGroup:一个用于资源共享的异步通道集合。处理IO事件和分配给CompletionHandler。(具体这块还没细看代码,后续再分析这块)
以一个简单监听服务端为例,基本过程是:
1. 启动一个服务端通道
2. 定义一个事件处理器,用户事件完成的时候处理,如消费数据。
3. 向系统注册一个感兴趣的事件,如接受数据,并把事件完成的处理器传递给系统。
4. 都已经交待完毕,能够只管继续作本身的事情了,操做系统在完成事件后经过其余的线程会自动调用处理器完成事件处理。
如下用一个例子来简单实现,一个服务端和客户端。服务端监听客户端的消息,并打印出来。
AIOServer.javahtml
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;
-
-
- 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");
- }
-
- @Override
- public 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.javajava
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的代码实现简单不少。网络