Java-IO

  1. 1.JAVA的I/O演进之路
    1. 1.1 I/O基础入门
    2. 1.2 linux网络I/O模型简介。
    3. 1.3 java的I/O演进
    4. 1.4 java的I/O发展简史

1.JAVA的I/O演进之路

  Java 之所以能够得到如此广泛的应用,除了拜托硬件平台的依赖,具有“一次编写、到处运行”的平台无关性特性外,另一个重要原因:其丰富二强大的类库以及众多第三方开源类库使得基于java语言的开发更加简单和便捷。

  java的一些类库在早期设计中功能并不完善或存在缺陷,其中最令人恼火的就是基于同步I/O 的socket通信类库,知道2002年2月13日JDK1.4 的发布,java才第一次支持非阻塞I/O,这个类库的提供为JDK的通信模型带来翻天覆地的变化。

1.1 I/O基础入门

  Java1.4 之前的早期版本,java对I/O的支持并不完善,开发人员在开发高性能I/O程序的时候,会面临一些巨大的挑战和困难,主要问题如下:

A: 没有数据缓冲区,I/O性能存在问题。

B: 没有C 或 C++ 中的Channel概念,只有输入和输出流。

C: 同步阻塞式I/O通信(BIO),通常会导致通信线程被长时间阻塞。

D: 支持的字符集有限,硬件可移植性不好。

  在java支持异步I/O之前的很长一段时间,高性能服务端开发领域一直被C 和C++长期占据,java的同步阻塞I/O被大家锁诟病。

1.2 linux网络I/O模型简介。

根据UNIX网络编程对I/O模型的分类,UNIX提供了5种I/O模型。

A: 阻塞I/O模型:

  最常用的I/O模型就是阻塞I/O模型,缺省情形下,所有文件操作都是阻塞的,
我们以套接字接口为例:在进程空间中调用recvfrom(应用程序),其系统调用直到数据包到达且被复制到应用进程的缓冲区或者发生错误时才返回,在此期间一直会等待,进程在从调用recvfrom开始到它返回的整段时间内都是被阻塞的,因此被称为 阻塞I/O模型。

B: 非阻塞I/O模型:

  Recvfrom从应用层到内核的时候,如果缓冲区没有数据的话,就直接返回一个ewouldblock错误,一般都对非阻塞I/O模型进行轮询检查这个状态,看内核是不是有数据到来。

C:I/O复用模型:

  Linux提供select/poll,进程通过将一个或多个fd传递给select或poll系统调用,阻塞在select操作上,这样select/poll 可以帮我们侦测多个fd是否处于就绪状态。Select/poll是顺序扫描fd是否就绪,而且支持的fd数据有限,因此它的使用受到了一些制约,Linux还提供了一个epoll系统调用,epoll使用基于事件驱动方式代替顺序扫描,因此性能更高,当有fd就绪时,立即回调函数rollback.

D:信号驱动I/O模型

  首先开启套接口信号驱动I/O功能,并通过系统调用sigaction执行一个信号处理函数(此系统调用立即返回,进程继续工作,它是非阻塞的)。当数据准备就绪时,就为改进程生成一个sigio信息,通过信号回调通知应用程序调用recvfrom来读取数据,并通知主循环函数处理数据。

E:异步I/O

  告知内核启动某个操作,并让内核在整个操作完成后(包括将数据从内核复制到用户自己的缓冲区)通知我们。这种模型与信号驱动模型的主要区别是:信号驱动I/O由内核通知我们何时开始一个I/O操作。异步I/O模型有内核通知我们I/O操作何时已经完成。

对于大多数程序员而言,不需要了解网络编程的底层细节,大家只需要知道这个概念,知道操作系统底层是支持异步I/O通信的,只不过在很长一段时间java并没有提供异步I/O通信的类库,导致很多原生的java程序员对这块很陌生。

1.3 java的I/O演进

  在JDK1.4 推出java nio之前,基于java和所有socket通信都采用了同步阻塞式(BIO),这种一请求一应答的通信模型简化了上层的应用开发,但在性能和可靠性方面却存在着巨大的瓶颈。

  当并发访问量增大、响应时间延迟增大之后,采用javaBIO开发的服务端软件只有通过硬件的不断扩容来满足高并发和低时延,它极大地增加了企业的成本,并且随着集群模式的不断膨胀,系统的可维护性也面临着巨大的挑战,只能采购性能更高的硬件服务器来解决问题,这导致了恶性循环。

因此,JDK1.4版本提供了新的NIO类库,java也就支持了非阻塞I/O

1.4 java的I/O发展简史

  JDK1.0 到JDK1.3,java的I/O类库都非常原始,很多Unix网络编程中的概念或者接口在I/O类库中都没有体现,例如Pipe、Channel、Buffer 和selector等。

  JDK1.4时,新增了java.nio包,提供了很多进行异步I/O开发的api和类库,主要的类和接口如下:

优点:

A: 进行异步I/O操作的缓冲区ByteBuffer

B: 进行异步I/O操作的Pipe

C: 各种I/O操作(异步或同步)的channel,包括ServerSocketChannel和SocketChannel.

D: 多种字符集的编码能力和解码能力。

E: 实现非阻塞I/O操作的多路复用器selector

F: 基于流行的perl实现的正则表达式类库

G: 文件通道FileChannel

新的Nio类库的提供,极大地促进了基于java的异步非阻塞编程的发展和应用。

缺点:

A: 没有统一的文件属性(例如读写权限)

B: api能力比较弱,例如目录的级联创建和递归遍历,往往需要自己实现

C: 底层存储系统的一些高级Api无法使用

D: 所有文件操作都是同步阻塞调用,不支持异步文件读写操作。

  JDK1.7 正式发布(2011年7月28日)。它的比较大的亮点将原来的NIO类库进行升级,被称为NIO2.0.

改进点:

A:提供能够批量获取文件属性的api,这些API具有平台无关性,不与特性的文件系统相耦合,另外它还提供了标准的文件系统的SPI,供各个服务提供商扩展实现。

B:提供AIO功能,支持基于文件的异步I/O操作和针对网络套接字的异步操作。

C: 完成JSR-51定义的通道功能,包括对配置和多播数据报的支持等。

文章标题:Java-IO

发布时间:2019-11-15, 15:43:15

最后更新:2019-11-15, 15:43:16