NIO&AIO编程模型

NIO线程模型

nio

什么是NIO线程模型?

上图是NIO的线程模型,  基于select实现,   这种线程模型的特色:  多条channel经过一个选择器和单挑线程绑定, 而且在这种编程模型中, Channel中相关业务逻辑不容许存在耗时的任务 , 若是必定会有耗时的逻辑, 请将它们放置到线程池中去运行,  由于这种模型虽然作到了非阻塞, 可是他并非真正的异步编程, 任何channel上的任何耗时的操做, 都会拖垮这个选择器, 进而拖垮整条线程 , 这也是为啥它会被称为 同步非阻塞java

 什么是同步?

  • 其一: 由于当channel中出现了耗时的操做时, 其余的channel不得不一样步等待
  • 其二: 从编码上看: NIO编程中 服务端的select() 会同步等待选择器感兴趣的事件发生
  • 其三: 从操做系统的角度上看, 程序使用的数据来自 网卡 -> 操做系统的内核缓冲区 -> 用户区, 当数据进入用户区后java程序即可以对其进行读写操做, 所谓同步就是: 数据进入用户区的过程当中,NIO编程模型须要同步并不停的询问

NIO线程模型的优势

NIO线程线程模型相对于传统的BIO来讲, 最大的优点就是在于 NIO线程模型中单条线程可同时为N个用户(Channel)服务, 而BIO编程模型让人诟病的地方就是, 任何一个新链接接入, 服务器都得为他开启不止一条新的线程去运行它, 这种BIO系统中, 并发确定不会很高编程

NIO适用场景:

NIO方式适用于链接数目多且链接比较短(轻操做)的架构,好比聊天服务器,并发局限于应用中,编程比较复杂,JDK1.4开始支持服务器

AIO (Asynchronous Input/Output )模型

什么是AIO?

AIO是(jdk1.7) 发行的 异步IO编程模型, 真正实现了异步IO, 基于Linux系统的 Epoll 机制实现网络

不管是NIO, 仍是AIO底层都没有改变网络通讯的基本步骤, 而是在这个基础上进行了一系列的升级架构

AIO的底层实现是由操做系统完成的, 数据在内核空间&用户空间的迁移, 咱们在编写代码时也是这样, 只须要调用 AIO.read() 或者是 AIO.write() 便可, 换句话说, 咱们的业务逻辑就成了 回调, 原来在操做系统处理数据的这个过程当中, 咱们的程序须要阻塞等待着, 亦或者放在线程池中运行, 而在AIO编程中这段等待时间差被省去了, 由于当操做系统认为数据还有没准备完时, 它是不会打扰咱们的程序的, 这时咱们的程序能够去处理其余的逻辑, 而一旦操做系统认为数据齐全了, 他就会回调咱们的提供的回调函数并发

  • 对应操做系统来讲, 当有流数据可读时, 操做系统会将流传入到read方法的缓冲区, 而后回调相关的 CompletionHandler
  • 对于写操做而言, 操做系统会将程序中Buffer里面数据写入到从用户空间写入到系统空间 再写入到网卡中, 写入完毕, 一样会回调相关的回调函数

AIO编程Server端的示例

下面贴出来一个AIO编程Server端的实例:异步

像下面的 read() write() accept() 全是异步的, 一经调用即刻返回, 不同的地方是咱们会提供一个回调对象, 留给操做系统, 当操做系统认为读写数据都到位了, 就会去回调这些函数async

public class AIOServer {
    private ExecutorService executorService;

    // 服务端的Channel
    private AsynchronousServerSocketChannel asynchronousServerSocketChannel;

    private AIOServer(int port) {
        init(port);
    }

    // 初始化
    private void init(int port) {
        System.out.println("aio server start with port " + port);

        executorService = Executors.newFixedThreadPool(5);

        try {
            // 开启服务端的通道
            asynchronousServerSocketChannel = AsynchronousServerSocketChannel.open();
            // 绑定端口
            asynchronousServerSocketChannel.bind(new InetSocketAddress(port));
            System.out.println("server start ... ");

            /**
             *  方法会异步的去接收一个请求, accept()一样是
             *  参数1 : this , 暂时理解成任意类型的
             *  参数2 : CompleteHandler -- 当请求到来后,会交付给 AIOServerHandler进行处理
             *
             * todo 在 AIO中的监听并非while(true), 而是相似递归的操做, 每次监听到客户端的请求后, 都须要在处理逻辑中开启下一次的监听
             */
            asynchronousServerSocketChannel.accept(this, new AIOServerHandler());
            System.out.println("------------------------------");
            // 阻塞程序
            try {
                TimeUnit.SECONDS.sleep(60);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public AsynchronousServerSocketChannel getAsynchronousServerSocketChannel() {
       return this.asynchronousServerSocketChannel;
    }

    public static void main(String[] args) {
        AIOServer aioServer = new AIOServer(9999);
    }
}

AIO的适用场景

AIO方式使用于链接数目多且链接比较长(重操做)的架构,好比相册服务器,充分调用OS参与并发操做,编程比较复杂,JDK7开始支持。异步编程

我是bloger 赐我白日梦, 欢迎关注我 --武汉加油函数