Java I/O


Java I/o

基础概念

Java 的I/O大概可以分成一下几类:

  1. 磁盘操作:File
  2. 字节操作:InputStream 和 OutputStream
  3. 字符操作:Reader 和 Writer
  4. 对象操作:Serializable
  5. 网络操作:Socket
  6. 新的输入/输出:NIO


Java I/O 使用了装饰者模式来实现。以 InputStream 为例,

InputStream 是抽象组件;

  • FileInputStream 是 InputStream 的子类,属于具体组件,提供了文件字节流的输入操作;
  • FilterInputStream 属于抽象装饰者,装饰者用于装饰组件,为组件提供额外的功能。例如 BufferedInputStream 为 FileInputStream 提供缓存的功能。
    InputStream的作用是用来表示那些从不同数据源产生输入的类。
  1. 字节数组
  2. String对象
  3. 文件
  4. “管道“,工作方式与实际管道类似,即一端输入另一端输出
  5. 其他数据源,如Internet连接等
    Reader 与 Writer
  • 不管是磁盘还是网络传输,最小的存储单元都是字节,而不是字符。但是在程序中操作的通常是字符形式的数据,因此需要提供对字符进行操作的方法。
  • InputStreamReader 实现从字节流解码成字符流;
  • OutputStreamWriter 实现字符流编码成为字节流。

常见的I/O模型对比

BIO

同步阻塞IO模型,当应用程序发起read之后,会一直阻塞,知道内核将数据准备就绪并把数据拷贝到用户空间,程序才会继续运行。

NIO

NIO模式下,系统调用read,如果发现没数据已经到达,就会立刻返回-1。使用轮询的方式,不断的尝试有没有数据到达。没有得到数据就等一小会再试继续轮询。

NIO解决了线程阻塞的问题 ,但是会带来两个新问题:

  • 如果有IO连接都要检查,那么就得一个一个的read。这会带来大量的线程上下文切换(read是系统调用,每调用一次就得在用户态和核心态切换一次)
  • 轮询的休息等待时间无法确定。这里是要猜多久之后数据才能到。等待时间设的太长,程序响应延迟就过大;设的太短,就会造成过于频繁的重试,干耗CPU而已。

多路复用IO

多路复用使用select,poll,epoll函数实现,主要是将多个进程的IO注册到同一管道上统一管理。管道会统一和内核进行交互,告诉操作系统要监视这些IO是否有事件发生。

IO 多路复用模型中,线程首先发起 select 调用,询问内核数据是否准备就绪,等内核把数据准备好了,用户线程再发起 read 调用。read 调用的过程(数据从内核空间->用户空间)还是阻塞的。
特点及相关说明:

  • IO多路复用是要和NIO一起使用的。尽管在操作系统级别,NIO和IO多路复用是两个相对独立的事情。也可以只用IO多路复用 + BIO,这时效果还是当前线程被卡住,没有达到IO多路复用的通知请求到来的效果。
  • IO多路复用说的是多个Socket或IO连接,只不过操作系统是一起监听他们的事件而已。

多个数据流共享同一个TCP连接的场景的确是有,比如Http2 Multiplexing就是指Http2通讯中多个逻辑的数据流共享同一个TCP连接。但这与IO多路复用是完全不同的问题。

  • IO多路复用的关键API调用(select,poll,epoll_wait)总是Block的
  • IO多路复用和NIO一起仅仅是解决了调度的问题,避免CPU在这个过程中的浪费,使系统的瓶颈更容易触达到网络带宽,而非CPU或者内存。要提高IO吞吐,还是提高硬件的容量(例如,用支持更大带宽的网线、网卡和交换机)和依靠并发传输(例如HDFS的数据多副本并发传输)。

AIO

不会

select/poll/epoll

操作系统级别提供了一些接口来支持IO多路复用,最早的是select、poll,其后epoll是Linux下的IO多路复用的实现。

  • select接口最早实现存在需要调用多次、线程不安全以及限制只能监视1024个链接的问题
  • poll接口修复了select函数的一些问题,但是依然不是线程安全的。
  • epoll接口修复了上述的问题,并且线程安全,会通知具体哪个连接有新数据。
  • epoll通过epoll_ctl()来注册一个文件描述符,一旦基于某个文件描述符就绪时,内核会采用类似callback的回调机制,迅速激活这个文件描述符,当进程调用epoll_wait()时便得到通知(不再需要遍历文件描述符,通过监听回调的机制,也是epoll的魅力)

评论
 Previous
排序算法 排序算法
相关资料:https://www.jianshu.com/p/47170b1ced23 冒泡排序算法描述 比较相邻的元素,如果前一个比后一个大,交换两个元素 从最开始的一对到最后一对,这样最后的元素就是数组里最大的数 重复以上步骤,除
2021-05-28
Next 
Java基础 Java基础
Java基础1.基本数据类型1.1 8种基本类型 1.2 包装类型将简单类型包装为类,含有以下用途 提供类的对象操作,如类型转换,进制转换等 集合不允许存放基本数据类型,使用包装类 包装类含有基本类型的相关属性,如最大值,最小值等 包装
2021-05-23
  TOC