1.NIO与IO、AIO的区别
IO | NIO | AIO |
面向流 | 面向缓冲 | 面向缓冲 |
同步阻塞IO | 同步非阻塞IO | 异步非阻塞 |
无通道 | 有通道 | 有通道 |
无选择器 | 有选择器 | 有选择器 |
它其实就是服务端创建一个ServerSocket, 然后就是客户端用一个Socket去连接服务端的那个ServerSocket, ServerSocket接收到了一个的连接请求就创建一个Socket和一个线程去跟那个Socket进行通讯。 | 一个线程处理大量的客户端的请求,通过一个线程轮询大量的channel,每次就获取一批有事件的channel,然后对每个请求启动一个线程处理即可。非阻塞,就那个selector一个线程就可以不停轮询channel,所有客户端请求都不会阻塞,直接就会进来,大不了就是等待一下排着队而已。 | 每个连接发送过来的请求,都会绑定一个Buffer,然后通知操作系统去完成异步的读,这个时间你就可以去做其他的事情。等到操作系统完成读之后,就会调用你的接口,给你操作系统异步读完的数据。 |
NIO即New IO,这个库是在JDK1.4中才引入的。NIO和IO有相同的作用和目的,但实现方式不同,NIO主要用到的是块,所以NIO的效率要比IO高很多。在Java 7中,NIO有了进一步的改进,也就是NIO 2,引入了异步非阻塞IO方式,也有很多人叫它AIO。 面向流与面向缓冲: Java IO面向流意味着每次从流中读一个或多个字节,直至读取所有字节,它们没有被缓存在任何地方。此外,它不能前后移动流中的数据。如果需要前后移动从流中读取的数据,需要先将它缓存到一个缓冲区。 Java NIO的缓冲导向方法略有不同。数据读取到一个它稍后处理的缓冲区,需要时可在缓冲区中前后移动。这就增加了处理过程中的灵活性。 阻塞与非阻塞IO: Java IO的各种流是阻塞的。这意味着,当一个线程调用read() 或 write() 时,该线程被阻塞,直到有一些数据被读取,或数据完全写入。该线程在此期间不能再干任何事情了。 Java NIO的非阻塞模式,使一个线程从某通道发送请求读取数据,如果目前没有数据可用时,就什么都不会获取,而不是保持线程阻塞,所以直至数据变的可以读取之前,该线程可以继续做其他的事情。 选择器(Selectors): Java NIO的选择器允许一个单独的线程来监视多个输入通道,可以注册多个通道使用一个选择器,然后使用一个单独的线程来“选择”通道。这种选择机制,使得一个单独的线程很容易来管理多个通道。
2.NIO基础概念
缓冲区Buffer:缓冲区有直接缓冲区(JVM堆内存)和非直接缓冲区(系统内核内存)之分。在NIO库中,所有数据都是用缓冲区处理的。在读取数据时,它是直接读到缓冲区中的; 在写入数据时,它也是写入到缓冲区中的 通道Channel:所有的 IO 在NIO 中都从一个Channel 开始。Channel 有点象流。 数据可以从Channel读到Buffer中,也可以从Buffer 写到Channel中。JAVA NIO中的一些主要Channel的实现:FileChannel、DatagramChannel、SocketChannel、ServerSocketChannel Selector:Selector允许单线程处理多个 Channel。如果应用打开了多个连接(通道),但每个连接的流量都很低,使用Selector就会很方便。
3.Buffer的Capacity,Position和Limit
容量(Capacity):缓冲区能够容纳的数据元素的最大数量。容量在缓冲区创建时被设定,并且永远不能被改变。 上界(Limit):写模式中等价于buffer的大小,即capacity;读模式中为当前缓冲区中一共有多少数据,即可读的最大位置。这意味着当调用filp()方法切换成读模式时,limit的值变成position的值,而position重新指向0。 位置(Position):下一个要被读或写的元素的位置。初始化为0,buffer满时,position最大值为capacity-1。切换成读模式的时候,position指向0。Position会自动由相应的 get( )和 put( )函数更新。 position和limit的值在读/写模式中是不一样的。capacity的值永远表示buffer的大小。
4.clear()和compact()的区别
当读完所有的数据想要重新写入数据时,可以调用clear或者compact方法。 当调用clear()方法的时候,position被设置为0,limit被设置为capacity,换句话说,buffer的数据虽然都还在,但是buffer被初始化了,处于可以被重写的状态。这也就意味着如果buffer中还有没被读取的数据,在执行clear之后,你无法知道数据读到哪儿了,剩下的数据还有多少。 如果还有没有读完的数据,但是想先写数据,可以用compact()方法,这样未读数据会放在buffer前端,可以在未读数据之后跟着写新的数据。compact()会复制未读数据到buffer前端,然后设置position为未读数据单位后面紧跟的位置。limit还是设置为capacity,这和clear是一样的。现在buffer处于可以写的状态,但是不会覆盖之前未读完的数据。
5.Socket 与 Http 对比
SOCKET:套接字,TCP/IP网络的API。Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。socket是在应用层和传输层之间的一个抽象层,它把TCP/IP层复杂的操作抽象为几个简单的接口供应用层调用已实现进程在网络中通信。 HTTP:应用层协议。HTTP(超文本传输协议)是利用TCP在两台电脑(通常是Web服务器和客户端)之间传输信息的协议。客户端使用Web浏览器发起HTTP请求给Web服务器,Web服务器发送被请求的信息给客户端。
协议 | 响应方式 | |
Socket | 属于传输层,因为 TCP / UDP协议属于传输层,解决的是数据如何在网络中传输的问题 | 请求—响应:建立网络连接后,当 客户端 向 服务器 发送请求后,服务器端才能向客户端返回数据。 |
HTTP | 属于 应用层,解决的是如何包装数据 | 服务器主动发送:建立网络连接后,服务器可主动发送消息给客户端,而不需要由客户端向服务器发送请求。 |