NIO线程模型

什么是NIO线程模型?

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

什么是同步?

  • 其一: 因为当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() 全是异步的, 一经调用即刻返回, 不一样的地方是我们会提供一个回调对象, 留给操作系统, 当操作系统认为读写数据都到位了, 就会去回调这些函数

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 赐我白日梦, 欢迎关注我 --武汉加油

NIO&AIO编程模型的更多相关文章

  1. 手动搭建I/O网络通信框架4:AIO编程模型,聊天室终极改造

    第一章:手动搭建I/O网络通信框架1:Socket和ServerSocket入门实战,实现单聊 第二章:手动搭建I/O网络通信框架2:BIO编程模型实现群聊 第三章:手动搭建I/O网络通信框架3:NI ...

  2. Java NIO系列教程(八)JDK AIO编程

    目录: Reactor(反应堆)和Proactor(前摄器) <I/O模型之三:两种高性能 I/O 设计模式 Reactor 和 Proactor> <[转]第8章 前摄器(Proa ...

  3. io编程,bio,nio,aio

    本文会从传统的BIO到NIO再到AIO自浅至深介绍,并附上完整的代码讲解. 下面代码中会使用这样一个例子:客户端发送一段算式的字符串到服务器,服务器计算后返回结果到客户端. 代码的所有说明,都直接作为 ...

  4. 手动搭建I/O网络通信框架3:NIO编程模型,升级改造聊天室

    第一章:手动搭建I/O网络通信框架1:Socket和ServerSocket入门实战,实现单聊 第二章:手动搭建I/O网络通信框架2:BIO编程模型实现群聊 在第二章中用BIO编程模型,简单的实现了一 ...

  5. 谈谈传统BIO网络编程模型的局限性与NIO

    先来看看我们的server端: 创建一个serversocket,进行监听,每来一个客户端,就启动一个新启动为其服务: private void createListenSocket() { //如果 ...

  6. Nio编程模型总结

    终于,这两天的考试熬过去了, 兴致冲冲的来整理笔记来, 这篇博客是我近几天的NIO印象笔记汇总,记录了对Selector及Selector的重要参数的理解,对Channel的理解,常见的Channel ...

  7. JDK AIO编程

    NIO2.0引入了新的异步通道的概念,并提供了异步文件通道和异步套接字通道的实现.异步通道提供两种方式获取获取操作结果. 通过java.util.concurrent.Future类来表示异步操作的结 ...

  8. Java IO编程全解(五)——AIO编程

    转载请注明出处:http://www.cnblogs.com/Joanna-Yan/p/7794151.html 前面讲到:Java IO编程全解(四)--NIO编程 NIO2.0引入了新的异步通道的 ...

  9. 深入学习Netty(3)——传统AIO编程

    前言 之前已经整理过了BIO.NIO两种I/O的相关博文,每一种I/O都有其特点,但相对开发而言,肯定是要又高效又简单的I/O编程才是真正需要的,在之前的NIO博文(深入学习Netty(2)--传统N ...

随机推荐

  1. Java逻辑思维训练题

    两柱香问题题目:有两柱不均匀的香,每柱香燃烧完需要1个小时,问:怎样用两柱香切出一个15分钟的时间段?这个题的重点就是怎么切. 答案:将甲香的一头点着,将乙香的两头点着,当乙香燃烧完时,说明已经过了半 ...

  2. 【Docker】删除镜像

    删除镜像:docker rmi [OPTIONS] IMAGE [IMAGE...] 1.删除所有未被 tag 标记和未被容器使用的镜像: docker image prune 2.删除所有未被容器使 ...

  3. 泛圈科技Yottachain区块链云存储打破传统云迎来价值数据存储

    随着物联网时代的发展,更多的数据随之产生.从智能设备到电脑再到视频游戏机,各种各样的信息从不同的电子产品源源不断地涌入.通常,人们将数据存储在本地驱动器中.但是,由于产生的数据量是无限的,超过了本地存 ...

  4. MySQL基础篇(03):系统和自定义函数总结,触发器使用详解

    本文源码:GitHub·点这里 || GitEE·点这里 一.系统封装函数 MySQL 有很多内置的函数,可以快速解决开发中的一些业务需求,大概包括流程控制函数,数值型函数.字符串型函数.日期时间函数 ...

  5. IHostingEnvironment VS IHostEnvironment - .NET Core 3.0中的废弃类型

    原文: https://andrewlock.net/ihostingenvironment-vs-ihost-environment-obsolete-types-in-net-core-3/ 作者 ...

  6. sql函数实用——字符函数(sqlserver与mysql对比)

    1.获取长度 sqlserver写法:关键字:len()    获取参数的字符数量 select  Len('aksjdhh')    输出结果 7 select len('张无忌ooo')   输出 ...

  7. 你确定你了解什么是linux系统?

    1.什么是linux发行版 就Linux的本质来说,它只是操作系统的核心,负责控制硬件.管理文件系统.程序进程等,并不给用户提供各种工具和应用软件.所谓工欲善其事,被必先利其器,一套在优秀的操作系统核 ...

  8. 鼠标右键新建Markdown文档

    首先放一张github某项目中.md文件中的内容图片 Windows系统下,使用 Typora 软件来进入Markdown文档的编写非常容易,而且入门门槛非常的低 存在的问题: 习惯了使用Markdo ...

  9. 天天都在用Git,那么你系统学习过吗?(一)学习过程

    你系统学习Git了吗? 使用Mac编程的好处,不是因为Mac长得好看 Git内容学习准备 如果你还没有用Git,就不要写代码了. GitHub仓库的使用. 新员工入职的时候,会让他先用一周的时间去学习 ...

  10. Class 'org.apache.tomcat.jdbc.pool.DataSource' not found

    把项目移动到新的运行环境时,明明包都导入了,项目也放进tomcat里面了,但是还会找不到该类 解决方法:项目右键选择底下的Properties ->project facets ->jav ...