1.IO模型主要分类:
(1)同步(synchronous) IO和异步(asynchronous) IO
(2)阻塞(blocking) IO和非阻塞(non-blocking)IO
(3)同步阻塞(blocking-IO)简称BIO
(4)同步非阻塞(non-blocking-IO)简称NIO
(5)异步非阻塞(synchronous-non-blocking-IO)简称AIO
2.BIO (同步阻塞I/O)
(1)数据的读取写入必须阻塞在一个线程内等待其完成
(2)jdk1.4以前是唯一的io现在,但程序直观简单易理解
(3)形象举例:烧开水
<1>有一排水壶在烧开水(10个水壶)
<2>BIO的工作模式就是, 叫一个线程停留在一个水壶那,直到这个水壶烧开
<3>其余水壶没有点火烧水,只有第一个烧开才去处理下一个水壶
<4>线程在等待水壶烧开的时间段什么都没有做
(4)BIO方式适用于
<1>连接数目比较小且固定的架构
<2>这种方式对服务端资源要求比较高,并发局限于应用中
3.NIO(同步非阻塞I/O)
(1)同时支持阻塞与非阻塞模式
(2)服务器实现模式为一个请求一个线程
<1>客户端发送的连接请求都会注册到多路复用器上
<2>多路复用器轮询到连接有IO请求时才启动一个线程进行处理
(3)形象举例:烧开水
<1>叫一个线程不断的轮询每个水壶的状态
<2>看看是否有水壶的状态发生了改变,从而进行下一步的操作
(4)NIO方式适用于
<1>连接数目多且连接比较短(轻操作)的架构
<2>聊天服务器,并发局限于应用中,编程比较复杂,jdk1,4开始支持
4.AIO (异步非阻塞I/O)
(1)异步非阻塞无需一个线程去轮询所有IO操作的状态改变
(2)在相应的状态改变后,系统会通知对应的线程来处理
(3)服务器实现模式为一个有效请求一个线程
<1>客户端的IO请求都是由操作系统先完成了再通知服务器用其启动线程进行处理
(4)形象举例:烧开水
<1>为每个水壶上面装了一个开关,水烧开之后,水壶会自动通知水烧开了
(5)AIO方式适用于
<1>连接数目多且连接比较长(重操作)的架构
<2>比如相册服务器,充分调用OS参与并发操作,编程比较复杂,jdk1.7开始支持
<3>AIO也被称为NIO2.0
5.IO与NIO区别
(1)IO面向流,NIO面向缓冲区
(2)IO的各种流是阻塞的,NIO是非阻塞模式
(3)IO无选择器,NIO有选择器(Selectors)
6.同步与异步的区别
(1)同步:发送一个请求,等待返回,再发送下一个请求,同步可以避免出现死锁,脏读的发生
(2)异步:发送一个请求,不等待返回,随时可以再发送下一个请求,可以提高效率,保证并发
(3)同步异步关注点在于消息通信机制
7.阻塞和非阻塞
(1)阻塞:传统的IO流都是阻塞式的
<1>阻塞调用是指当一个线程调用read()或者write()方法时,当前线程会被挂起
<2>调用线程只有在得到结果之后才会返回
<3>当服务器端需要处理大量的客户端时,性能急剧下降
(2)非阻塞:NIO是非阻塞式的
<1>当线程从某通道进行读写数据时,若没有数据可用时,该线程会去执行其他任务
<2>线程通常将非阻塞IO的空闲时间用于在其他通道上执行IO操作
<3>单独的线程可以管理多个输入和输出通道
<4>NIO让服务器端使用一个或有限几个线程来同时处理连接到服务器端的所有客户端
(3)阻塞与非阻塞关注的是程序在等待调用结果时(消息、返回值)的状态
8.NIO的3个核心概念
(1)缓冲区Buffer
<1>Buffer是一个对象,在NIO中,所有的数据都是用缓冲区处理
<2>它包含一些要写入或者读出的数据
2.1.在面向流的I/O中,可以将数据写入或者将数据直接读到Stream对象中
<3>缓冲区实质是一个数组
3.1.通常它是一个字节数组(ByteBuffer),也可以使用其他类的数组
3.2.一个缓冲区不仅仅是一个数组
3.3.缓冲区提供了对数据的结构化访问以及维护读写位置(limit)等信息
3.4.每一种Java基本类型(除了Boolean)都对应一种缓冲区
(2)通道Channel
<1>通过它读取和写入数据,他就像自来水管一样,网络数据通过Channel读取和写入
<2>通道和流不同之处在于通道是双向的,流只是在一个方向移动
<3>通道可以用于读,写或者同时用于读写
<4>Channel是全双工的,所以它比流更好地映射底层操作系统的API,
4.1.在UNIX网络编程中,底层操作系统的通道都是全双工的,同时支持读和写
<5>Channel有四种实现
5.1.FileChannel:是从文件中读取数据
5.2.DatagramChannel:从UDP网络中读取或者写入数据
5.3.SocketChannel:从TCP网络中读取或者写入数据
5.4.ServerSocketChannel:允许监听来自TCP的连接,就像服务器一样
5.4.1.每一个连接都会有一个SocketChannel产生
(3)多路复用选择器Selector
<1>Selector选择器可以监听多个Channel通道感兴趣的事情
<2>Selector只能管理非阻塞的通道,FileChannel是阻塞的,无法管理
<3>关键对象:
3.1.Selector:选择器对象,通道注册、通道监听对象和Selector相关
3.2. SelectorKey:通道监听关键字,通过它来监听通道状态
<4>监听注册:
4.1.监听注册在Selector:
4.2.socketChannel.register(selector, SelectionKey.OP_READ);
<5>监听的事件有
5.1.OP_ACCEPT: 接收就绪,serviceSocketChannel使用的
5.2.OP_READ: 读取就绪,socketChannel使用
5.3.OP_WRITE: 写入就绪,socketChannel使用
5.4.OP_CONNECT: 连接就绪,socketChannel使用
9.NIO的应用
(1)NIO成功的应用在了各种分布式、即时通信和中间件Java系统中
(2)是一种高效,且扩展性很强的通信架构
(3)Dubbo默认使用Netty作为基础通信组件,用于实现各进程节点之间的内部通信
(4)Jetty、Mina、Netty、Dubbo、ZooKeeper等都是基于NIO方式实现
<1>Mina出身于开源界的大牛Apache组织
<2>Netty出身于商业开源大亨Jboss
<3>Dubbo阿里分布式服务框架
10.NIO框架
(1)Netty是目前最流行的一个Java开源框架NIO框架
<1>Netty提供异步的、事件驱动的网络应用程序框架和工具
<2>用以快速开发高性能、高可靠性的网络服务器和客户端程序
<3>相比JDK原生NIO,Netty提供了相对十分简单易用的API,非常适合网络编程
(2)Netty是基于IO的多路复用机制实现的
<1>IO多路复用,在没有用特殊异步api的情况下,还是同步的操作
<2>一个线程会专门处理激活的IO消息
<3>当有多个IO消息被激活时,处理过程仍然时一个一个同步进行的
(3)多路复用技术
<1>多路指多个TCP连接(即socket或者channel),复用指复用一个或几个线程
<2>可以让单个线程高效的处理多个连接请求(尽量减少网络IO的时间消耗)
<3>单线程的原子操作,避免上下文切换的时间和性能消耗
<4>Netty,Redis都使用了IO多路复用机制
<5>多路复用机制的实现方式有三种:select/poll/epoll和recvfrom