java IO总结(BIONIOAIO)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java IO总结(BIONIOAIO)相关的知识,希望对你有一定的参考价值。

1、BIO编程

1.1、传统的BIO编程

网络编程的基本模型是C/S模型,即两个进程间的通信。

服务端提供IP和监听端口,客户端通过连接操作想服务端监听的地址发起连接请求,通过三次握手连接,如果连接成功建立,双方就可以通过套接字进行通信。

传统的同步阻塞模型开发中,ServerSocket负责绑定IP地址,启动监听端口;Socket负责发起连接操作。连接成功后,双方通过输入和输出流进行同步阻塞式通信。

简单的描述一下BIO的服务端通信模型:

采用BIO通信模型的服务端,通常由一个独立的Acceptor线程负责监听客户端的连接,它接收到客户端连接请求之后,为每个客户端创建一个新的线程进行链路处理,处理完成后,通过输出流返回应答给客户端,线程销毁。即典型的一请求一应答通宵模型。

该模型最大的问题就是缺乏弹性伸缩能力,当客户端并发访问量增加后,服务端的线程个数和客户端并发访问数呈1:1的正比关系,Java中的线程也是比较宝贵的系统资源,线程数量快速膨胀后,系统的性能将急剧下降,随着访问量的继续增大,系统最终就死-掉-了。

BIO示例:

 

 

可以看出,BIO主要的问题在于每当有一个新的客户端请求接入时,服务端必须创建一个新的线程来处理这条链路,在需要满足高性能、高并发的场景是没法应用的,因为大量创建新的线程会严重影响服务器性能,甚至罢工。

1.2、使用线程池改进BIO编程

为了改进这种一连接一线程的模型,我们可以使用线程池来管理这些线程:

 

 我们知道,如果使用CachedThreadPool线程池,不限制线程数量,其实除了能自动帮我们管理线程的复用,看起来也就像是1:1的请求:线程数模型,而使用FixedThreadPool限制了线程的最大数量,保证了系统资源的控制,实现了N:M的伪异步I/O模型。但是,限制了线程数量,如果发生大量并发请求以致超过了最大线程数,请求将一直等待直到线程池中的有空闲的线程可以被复用。而对Socket的输入流读取时,也就一直阻塞。

 

 

所以在读取数据较慢时,比如数据量大、网络传输慢等,大量并发的情况下,其他接入的消息,只能一直等待,这就是最大的弊端。而NIO可以解决这个难题。

 

2、NIO 编程

JDK 1.4中的java.nio.*包中引入新的Java I/O库,其目的是提高速度。实际上,“旧”的I/O包已经使用NIO重新实现过,即使我们不显式的使用NIO编程,也能从中受益。速度的提高在文件I/O和网络I/O中都可能会发生,但本文只讨论后者。

NIO提供了与传统BIO模型中的Socket和ServerSocket相对应的SocketChannel和ServerSocketChannel两种不同的套接字通道实现。

2.1、缓冲区 Buffer

Buffer是一个对象,包含一些要写入或者读出的数据。

在NIO库中,所有数据都是用缓冲区处理的。在读取数据时,它是直接读到缓冲区中的;在写入数据时,也是写入到缓冲区中。任何时候访问NIO中的数据,都是通过

缓冲区进行操作。缓冲区实际上是一个数组,并提供了对数据结构化访问以及维护读写位置等信息。

具体的缓存区有这些:ByteBuffe、CharBuffer、 ShortBuffer、IntBuffer、LongBuffer、FloatBuffer、DoubleBuffer。他们实现了相同的接口:Buffer。

2.2、通道 Channel

我们对数据的读取和写入要通过Channel,它就像水管一样,是一个通道。通道不同于流的地方就是通道是双向的,可以用于读、写和同时读写操作。

底层的操作系统的通道一般都是全双工的,所以全双工的Channel比流能更好的映射底层操作系统的API。

Channel主要分两大类:

1.SelectableChannel:用户网络读写

2.FileChannel:用于文件操作

后面代码会及的 ServerSocketChannel 和 SocketChannel 都是 SelectableChannel 的子类

2.4、多路复用器 Selector

Selector是Java  NIO 编程的基础。

Selector提供选择已经就绪的任务的能力:Selector会不断轮询注册在其上的Channel,如果某个Channel上面发生读或者写事件,这个Channel就处于就绪状态,会被

Selector轮询出来,然后通过SelectionKey可以获取就绪Channel的集合,进行后续的I/O操作。

一个Selector可以同时轮询多个Channel,因为JDK使用了epoll()代替传统的select实现,所以没有最大连接句柄1024/2048的限制。所以,只需要一个线程负责Selector

的轮询,就可以接入成千上万的客户端。

NIO示例:

   

 

 

   

   

 

 

 

 

 

 

笔记内容转自【http://blog.csdn.net/anxpp/article/details/51512200

以上是关于java IO总结(BIONIOAIO)的主要内容,如果未能解决你的问题,请参考以下文章

java IO总结(BIONIOAIO)

Java 网络IO编程总结二(BIONIOAIO)

Java 网络IO编程总结二(BIONIOAIO)

Java 网络IO编程总结(BIONIOAIO均含完整实例代码)

Java 网络IO编程总结(BIONIOAIO均含完整实例代码)

Java 网络IO编程总结(BIONIOAIO均含完整实例代码)