资讯专栏INFORMATION COLUMN

jdk7:浅谈 AIO NIO2.0

wanghui / 520人阅读

摘要:一概述在引入同步非阻塞包之后,终于在版本加入了异步的。注意,无论用还是,这里的调用都是非阻塞的立即返回。不过,由于朝鲜还没有研发出能够重返大气层的运载火箭,所以大浦洞号尚不具备搭载弹头的攻击能力。

一、概述

JDK在1.4引入NIO(同步非阻塞)包之后,终于在1.7版本加入了异步IO的AIO。
同步异步阻塞和非阻塞等概念,建议参考 《Unix网络编程》 卷1. ,这里只谈AIO的api。

二、主要的类

AsynchronousSocketChannel

AsynchronousServerSocketChannel

AsynchronousFileChannel

AsynchronousDatagramChannel

三、通过aio实现server

先看下AsynchronousServerSocketChannel,它有两个构造方法,选择哪个构造方法,也就选择了不同的编程模型,分别是Future机制和Handler回调机制。Future机制适合需要同步等待获取结果的,Handler机制则看上去则更像纯异步。当然,结果都是一样的,看自己需要或者喜欢哪个模型吧。

public abstract Future accept();

public abstract  void accept(A attachment,
                                    CompletionHandler handler);

先看看AsynchronousServerSocketChannel来启动一个server,代码如下。注意accept,无论用future还是handler,这里的调用都是非阻塞的立即返回。这里选用handler的方式,如果有客户端连接上来,handler的会被回调。

public class AioServer {
    
    public final int port = 8080;
    public final int backlog = 2; //跟bio和nio的backlog其实是一样的。指定accpet等待队列的长度
    private AioAcceptHandler acceptHandler;
    private AsynchronousServerSocketChannel serverSocket;
    
    public static void main(String[] args) throws Exception {
        new AioServer().startup();
    }

    private void startup() throws Exception {
        int availableProcessors = Runtime.getRuntime().availableProcessors();
        ExecutorService channelWorkers = Executors.newFixedThreadPool(availableProcessors * 2);
        AsynchronousChannelGroup channelGroup = AsynchronousChannelGroup.withCachedThreadPool(channelWorkers , 1);
        serverSocket = AsynchronousServerSocketChannel.open(channelGroup);
        serverSocket.bind(new InetSocketAddress(port), backlog);
        acceptHandler = new AioAcceptHandler();
        accept();
    }

    public void accept() {
        serverSocket.accept(this, acceptHandler); //非阻塞
    }
}

接下来CompletionHandler的接口吧,代码如下。看到泛型的 V result 就说嘛,当我们使用CompletionHandler的时候,自己需要清楚的知道返回结果是什么。
比如accept中指定的CompletionHandler。它是处理接受连接的,成功返回的话,结果就是套接字,那么我们就要指定泛型V的实际类型为AsynchronousSocketChannel。
再比如read方法中指定CompletionHandler。read是将数据读取到ByteBuffer,而回调CompletionHandler的时候,结果V是读取的数量。所以我们就要指定泛型V的实际类型为Integer。
具体可以看下面的实现代码 AioAcceptHandler 和 AioReadHandler。

public interface CompletionHandler {
    //调用结果,附件
    void completed(V result, A attachment);
    //异常对象、附件
    void failed(Throwable exc, A attachment);
}

AioAcceptHandler

public class AioAcceptHandler implements CompletionHandler{

    public void completed(AsynchronousSocketChannel socket, AioServer aioServer) {
        try {
            System.out.printf("客户端%s连接成功.
", socket.getRemoteAddress().toString());
            readData(socket);
        } catch (Exception e) {
            e.printStackTrace();
            try {
                socket.close();
            } catch (IOException e1) {}
        } finally {
            aioServer.accept();
        }
    }

    private void readData(AsynchronousSocketChannel socket) {
        ByteBuffer buf = ByteBuffer.allocate(32);   //测试时,可以不设置太大,观察aio的多次read
        socket.read(buf, buf, new AioReadHandler(socket));
    }

    public void failed(Throwable exc, AioServer aioServer) {
        exc.printStackTrace();
    }
}

AioReadHandler

public class AioReadHandler implements CompletionHandler {

    private AsynchronousSocketChannel socket;
    private ByteArrayOutputStream baos = new ByteArrayOutputStream();
    public AioReadHandler(AsynchronousSocketChannel socket){
        this.socket = socket;
    }
    
    public void completed(Integer result, ByteBuffer buf) {
        System.out.println("result = " + result + " buf = " + buf);
        if (result > 0) {
            buf.flip();
            try {
                baos.write(buf.array()); 
            } catch (IOException e) {
                e.printStackTrace();
            }
            buf.clear();
            socket.read(buf, buf, this);
        } else if (result == -1) { //result为-1的时候,客户端的socket已经正常关闭。
            try {
                System.out.printf("客户端%s已经断开.
", socket.getRemoteAddress().toString());
                String info = new String(baos.toByteArray(), Charset.forName("UTF8"));
                System.out.println(info);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                buf = null;
                try {
                    socket.close();
                } catch (IOException e) {}
            }
        }
    }

    public void failed(Throwable exc, ByteBuffer buf) {
        exc.printStackTrace();
    }
}

基本上,一个简单的AIOServer就上面这点代码拉。实际上我感觉代码比NIO用Selector的方式还是简单清晰多了。至于aio的原理,实际上就是去看看epoll等资料就知道了。

这里附上一个测试的客户端代码:

public class BioClient {
    public static void main(String[] args) throws Exception {
        String txt = "美国在发布的朝鲜军力评估报告中也认为:“朝鲜发展航天运载工具对开发射程可达美国的远程导弹意义重要,射程也许能覆盖美国部分地区。不过,由于朝鲜还没有研发出能够重返大气层的运载火箭,所以‘大浦洞2号’尚不具备搭载弹头的攻击能力。”";
        Socket socket = new Socket("localhost", 8080);
        PrintStream print = new PrintStream(socket.getOutputStream());
        print.print(txt);
        print.close();
        socket.close();
        System.out.println("ok.");
    }
}

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/65706.html

相关文章

  • java中的AIO

    摘要:会关联线程池,它的任务是接收处理事件,并分发给负责处理通道中操作结果的结果处理器。跟通道中发起的操作关联的结果处理器确保是由线程池中的某个线程产生。基本思想是主线程会派一个侦查员到独立的线程中执行操作。 简介 jdk7中新增了一些与文件(网络)I/O相关的一些api。这些API被称为NIO.2,或称为AIO(Asynchronous I/O)。AIO最大的一个特性就是异步能力,这种能力...

    邹强 评论0 收藏0
  • Netty序章之BIO NIO AIO演变

    摘要:后改良为用线程池的方式代替新增线程,被称为伪异步。最大的问题是阻塞,同步。每次请求都由程序执行并返回,这是同步的缺陷。这些都会被注册在多路复用器上。多路复用器提供选择已经就绪状态任务的能力。并没有采用的多路复用器,而是使用异步通道的概念。 Netty是一个提供异步事件驱动的网络应用框架,用以快速开发高性能、高可靠的网络服务器和客户端程序。Netty简化了网络程序的开发,是很多框架和公司...

    VincentFF 评论0 收藏0
  • Netty序章之BIO NIO AIO演变

    摘要:后改良为用线程池的方式代替新增线程,被称为伪异步。最大的问题是阻塞,同步。每次请求都由程序执行并返回,这是同步的缺陷。这些都会被注册在多路复用器上。多路复用器提供选择已经就绪状态任务的能力。并没有采用的多路复用器,而是使用异步通道的概念。 Netty是一个提供异步事件驱动的网络应用框架,用以快速开发高性能、高可靠的网络服务器和客户端程序。Netty简化了网络程序的开发,是很多框架和公司...

    CntChen 评论0 收藏0
  • Java NIO浅析

    摘要:阻塞请求结果返回之前,当前线程被挂起。也就是说在异步中,不会对用户线程产生任何阻塞。当前线程在拿到此次请求结果的过程中,可以做其它事情。事实上,可以只用一个线程处理所有的通道。 准备知识 同步、异步、阻塞、非阻塞 同步和异步说的是服务端消息的通知机制,阻塞和非阻塞说的是客户端线程的状态。已客户端一次网络请求为例做简单说明: 同步同步是指一次请求没有得到结果之前就不返回。 异步请求不会...

    yeooo 评论0 收藏0

发表评论

0条评论

wanghui

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<