上图是NIO的线程模型,??基于select实现, ? 这种线程模型的特点: ?多条channel通过一个选择器和单挑线程绑定, 并且在这种编程模型中, Channel中相关业务逻辑不允许存在耗时的任务 , 如果一定会有耗时的逻辑, 请将它们放置到线程池中去运行,? 因为这种模型虽然做到了非阻塞, 但是他并不是真正的异步编程, 任何channel上的任何耗时的操作, 都会拖垮这个选择器, 进而拖垮整条线程 , 这也是为啥它会被称为 同步非阻塞
select()
会同步等待选择器感兴趣的事件发生NIO线程线程模型相对于传统的BIO来说, 最大的优势就是在于 NIO线程模型中单条线程可同时为N个用户(Channel)服务, 而BIO编程模型让人诟病的地方就是, 任何一个新连接接入, 服务器都得为他开启不止一条新的线程去运行它, 这种BIO系统中, 并发肯定不会很高
NIO方式适用于连接数目多且连接比较短(轻操作)的架构,比如聊天服务器,并发局限于应用中,编程比较复杂,JDK1.4开始支持
AIO是(jdk1.7) 发行的 异步IO编程模型, 真正实现了异步IO, 基于Linux系统的 Epoll 机制实现
无论是NIO, 还是AIO底层都没有改变网络通信的基本步骤, 而是在这个基础上进行了一系列的升级
AIO的底层实现是由操作系统完成的, 数据在内核空间&用户空间的迁移, 我们在编写代码时也是这样, 只需要调用 AIO.read()
或者是 AIO.write()
即可, 换句话说, 我们的业务逻辑就成了 回调, 原来在操作系统处理数据的这个过程中, 我们的程序需要阻塞等待着, 亦或者放在线程池中运行, 而在AIO编程中这段等待时间差被省去了, 因为当操作系统认为数据还有没准备完时, 它是不会打扰我们的程序的, 这时我们的程序可以去处理其他的逻辑, 而一旦操作系统认为数据齐全了, 他就会回调我们的提供的回调函数
下面贴出来一个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方式使用于连接数目多且连接比较长(重操作)的架构,比如相册服务器,充分调用OS参与并发操作,编程比较复杂,JDK7开始支持。
我是bloger 赐我白日梦, 欢迎关注我 --武汉加油
原文:https://www.cnblogs.com/ZhuChangwu/p/12237223.html