Java IO

BIO

基于阻塞IO模型,通常使用一个单独的线程接受客户端的连接,连接建立之后,每个客户端的请求都会有一个线程去处理,因此整个线程数与并发请求数是1:1的关系。

整个模型相对简单;但是缺点也很明显,线程是很宝贵的资源,在并发请求数上去之后,线程数膨胀导致系统性能急剧下降。

可以通过设置线程池大小来避免线程数的无限膨胀。但无法提高并发能力和解决前面请求阻塞会影响后面请求处理的问题。

NIO

Channel

在NIO中表示通道,提供读写的抽象,类似流,但是Channel是双通道的,可读可写。
根据不同的数据传输场景,Channel有很多种实现。

  • FileChannel 从文件中读写数据。
  • DatagramChannel 能通过UDP读写网络中的数据。
  • SocketChannel 能通过TCP读写网络中的数据。
  • ServerSocketChannel可以监听新进来的TCP连接,像Web服务器那样。对每一个新进来的连接都会创建一个SocketChannel。

Buffer

缓冲区的抽象,NIO库中,所有的数据都是用缓冲区处理的(读/写)。
根据操作类型的不同,Buffer有几种类型:ByteBuffer(常用)、CharBuffer、ShortBuffer等等。
使用Buffer读写数据一般遵循以下四个步骤:

  • 写入数据到Buffer
  • 调用flip()方法。当向buffer写入数据时,buffer会记录下写了多少数据。一旦要读取数据,需要通过flip()方法将Buffer从写模式切换到读模式。在读模式下,可以读取之前写入到buffer的所有数据。
  • 从Buffer中读取数据
  • 调用clear()方法或者compact()方法

Buffer有三个属性:

  • capacity:作为一个内存块,Buffer有一个固定的大小值,也叫“capacity”.你只能往里写capacity个byte、long,char等类型。
  • position:当你写数据到Buffer中时,position表示当前的位置。初始的position值为0.当一个byte、long等数据写到Buffer后, position会向前移动到下一个可插入数据的Buffer单元。position最大可为capacity – 1.
    当读取数据时,也是从某个特定位置读。当将Buffer从写模式切换到读模式,position会被重置为0. 当从Buffer的position处读取数据时,position向前移动到下一个可读的位置。
  • limit:在写模式下,Buffer的limit表示你最多能往Buffer里写多少数据。 写模式下,limit等于Buffer的capacity。
    当切换Buffer到读模式时, limit表示你最多能读到多少数据。因此,当切换Buffer到读模式时,limit会被设置成写模式下的position值。换句话说,你能读到之前写入的所有数据(limit被设置成已写数据的数量,这个值在写模式下就是position)

Buffer常用方法

  • rewind()方法: 将position重置为0,这时可以重读Buffer所有数据。
  • clear()方法: position将被设回0,limit被设置成 capacity的值。换句话说,Buffer 被清空了。
  • compact()方法: 将所有未读的数据拷贝到Buffer起始处。然后将position设到最后一个未读元素正后面。limit属性依然像clear()方法一样,设置成capacity。现在Buffer准备好写数据了,但是不会覆盖未读的数据。
  • mark()与reset()方法:调用Buffer.mark()方法,可以标记Buffer中的一个特定position。之后可以通过调用Buffer.reset()方法恢复到这个position。

Selector

多路复用器。Selector不断轮询注册在其上的Channel,如果某个Channel上面发生读/写事件,则会被该Selector轮询出来,然后通过SelectionKey获取就绪Channel的集合,进行对应的IO操作。

JDK采用epoll实现Selector。

AIO

NIO 2.0提供了异步通道的概念,异步通道的IO操作都需要提供一个CompletionHandler来进行IO操作成功/失败的回调处理。对应了事件驱动IO,真正实现了异步非阻塞IO.

你可能感兴趣的:(Java IO)