nio : non-blocking io 非阻塞IO
channel 有点像stream ,他就是读写数据的双向通道,可以从channel将数据读入buffer,也可以将buffer的数据写入channel,之前的stream 要么输入,要么输出;channel 比stream更加底层 。
FileChannel:用于文件的读取和写入操作。可以从文件中读取数据到缓冲区,也可以将数据从缓冲区写入文件。
SocketChannel:用于通过TCP协议进行网络通信。可以连接到远程服务器并发送和接收数据。
ServerSocketChannel:用于监听TCP连接请求。可以接受来自客户端的连接请求,并创建对应的SocketChannel进行通信。
DatagramChannel:用于通过UDP协议进行网络通信。可以发送和接收UDP数据包。
这些Channel的功能主要包括:
读取数据:可以从Channel中读取数据到缓冲区,供后续处理使用。
写入数据:可以将数据从缓冲区写入到Channel中,发送给对应的目标。
非阻塞模式:可以将Channel设置为非阻塞模式,以便在没有数据可读或可写时立即返回,而不是一直等待。
文件操作:FileChannel可以进行文件的读取和写入操作,包括读取文件内容、写入文件内容、文件的位置操作等。
网络通信:SocketChannel和ServerSocketChannel可以进行网络通信,包括连接远程服务器、发送和接收数据等。
这些Channel提供了更高级别的IO操作,相比于传统的InputStream和OutputStream,更加灵活和高效。通过使用这些Channel,可以实现更好的IO性能和更多的IO操作控制。
Buffer对象具有以下几个重要的属性和方法:
容量(Capacity):表示Buffer的最大容量,即它可以存储的最大数据量。
位置(Position):表示当前读写的位置,初始位置为0。
限制(Limit):表示有效数据的末尾位置,初始限制为容量。
标记(Mark):用于临时存储位置的标记,可以通过调用mark()方法设置标记,通过调用reset()方法恢复到标记位置。
读写操作:可以通过put()方法将数据写入Buffer,通过get()方法从Buffer中读取数据。
翻转(Flip):将Buffer从写模式切换到读模式,即将限制设置为当前位置,位置设置为0。
清空(Clear):将Buffer从读模式切换到写模式,即将位置和限制都设置为容量。
压缩(Compact):将未读取的数据复制到Buffer的起始位置,然后将位置设置为未读取数据的末尾。
Buffer提供了一种方便的方式来处理数据,可以通过读写操作来操作Buffer中的数据,并且可以通过翻转、清空等方法来控制读写的位置和限制。在NIO中,Buffer与Channel配合使用,可以实现高效的数据读写操作。
selector但从字面意思上不好理解,接下来需要结合服务器的设计演化来理解它的用途
缺点:连接数一多就不行了,大量数据来了,就会创建大量thread,到一定程度会造成oom。
而且线程上下文切换开销也会增大。因为你这个多线程我这个几个cpu吃不住。
虽然避免了oom ,降低了上下文切换的开销。但是他是在阻塞模式下工作的,就好比你的线程池里的一个线程,只能等待服务完一个socket之后才能服务完另一个socket。所以他只适合短链接的场景。
selector 的作用就是配合一个线程来管理多个channel,获取这些channel 上发生的事件,这些 channel 工作在非阻塞模式下,不会让线程吊死在一个 channel 上。适合连接数特别多,但流暴低的场景 (low traffic)
调用selector 的select0 会阻塞直到channel 发生了读亏就緒事件,这些事件发生,select 方法就会返回这些事件交给 thread 来处理
讲个小案例就是说 selector好比服务员 ,channel 好比客人。channelA把服务员selector说了我来一份饺子 ,又说我在想想,与此同时channelB说我来个包子,这时候selector不会等着A,而是转头给B一个包子。但是a是个吃货我要这个还要哪个等等 这时候channel会一直服务a,但如果a说我在想想还要啥,selector就去服务其他客人了。 这就是非阻塞的去处理事件