Java中的几种IO

BIO

采用BIO通信模式的服务端,通常由一个独立的Acceptor线程负责监听客户端的连接, 我们一般通过在while(true) 循环中服务端会调用accept() 方法等待接收客户端的连接方式监听请求,请求一旦接收到一个连接请求,就可用建立通信套接字在这个通信套接字上进行读写操作,此时不能再接收其它客户端连接请求,只能等待当前连接的客户端操作执行完成,不过可用通过多线程的方式支持多个客户端的连接

一请求一应答的原理

socket.accept() , socket.read() , socket.write() 涉及三个主要函数都是同步阻塞的

它在接收客户端连接请求之后为每一个客户端创建一个新的线程进行链路处理,处理完成之后,通过输出流返回应答给客户端,线程销毁,这就是典型的一请求一应答通信模型

问题:

如果一个连接不做任何事情的话,这个线程永远无法结束对这个客户端的操作,就会造成不必要的线程开销

解决:

  • 通过线程池机制改善,线程池还可以让线程的创建和回收成本相对较低
  • 使用 FixedThreadPool 可以有效的控制线程的最大数量,保证了系统有限的资源的控制,实现了N(客户端i请求数量) 远大于M(处理客户端的请求线程数量)的伪异步操作

在java虚拟机中,线程是宝贵的资源 ,线程的创建,销毁,切换成本都是很高的,尤其是Linux这种线程即进程的操作系统中, 如果并法访问量增加会导致线程数急剧膨胀可能会导致线程堆栈溢出,创建新线程失败等问题,最终导致宕机或僵死,不能对外提供服务

在活动链接数不是特别高(小于单机1000) 的情况下,这种模型是不错的,可以让每个连接专注于自己的I/O 并且来编程模型简单,线程池本身就是一个天然的漏斗,可以缓冲一些系统处理不了的连接或者请求,但是,当面对十万甚至百万级别连接的时候,传统BIO模型是无能为力的

NIO (NEW I/O)

NIO是一种同步非阻塞的 I/O模型 对应的Java.nio包,提供了Channel,Selector,Buffer等抽象

NIO提供了传统BIO模型中 socket 和与 ServerSocket 对应的 SocketChannelServerSocketChannel 两种不同的套接字通道实现,两种通道都支持阻塞和非阻塞两种模式,

  • 对于低负载,低并发的应用程序,可以使用同步阻塞I/O提升开发效率和更好的维护性
  • 对于高负载,高并发的应用,应使用NIO的非阻塞模式来开发
NIO读数据和写数据的方式

通常来说,NIO中的所有IO都是从Channel开始的

  • 从通道进行数据读取: 创建一个缓冲区 然后请求通道读取数据
  • 从通道进行数据写入 创建一个缓冲区, 填充数据,并要求通道写入数据
NIO的核心组件
  • Channel(通道)
  • **Buffer **(缓冲区)
  • Selector (选择器)

NIO与IO的区别

IO是阻塞的,NIO是非阻塞的

java NIO使我们可以进行非阻塞IO操作,比如说,单线程中从通道读取数据到buffer,同时可以继续做别的事情,当数据读取到buffer中后,线程再继续处理数据,写数据也是一样,另外,非阻塞写也是如此. 一个线程请求写入一些数据到某通道,但不需要等待它完全写入,这个线程同时可以还别的事情

java IO的各种流是阻塞的,这意味着,当一个线程调用 read()write() 时候,该线程被阻塞,直到有一些数据被读取,或数据完全写入 否则该线程在此期间不能再干任何事情

Buffer(缓冲区)

IO 面向流(Stream oriented),而 NIO面向缓冲区(Buffer oriented)

  • Buffer是一个对像,它包含了一些要写入或者读取的数据 在NIO类库中加入Buffer对象,体现了新库和原I/O的一个重要区别
  • 在面向流I/O中,可以将数据直接写入或者将数据直接读取到Stream对象中 虽然Stream中也有Buffer开头的扩展类,但只是流的包装类,还是从流读取缓冲区,而NIO却是直接读到Buffer中进行操作
  • NIO库中,所有数据都是使用缓冲区处理的,在读取数据时,它是直接读取到缓冲区的,在写入数据时,写入到缓冲区,事实上,每一种Java基本类型(除了Boolean类型) 都对应由一种缓冲区
Channel通道

NIO通过 Channel(通道) 进行读写

  • 通道时双向的,可读也可以写
  • 普通I/O用流,流的读写是单向的

无论读写,通道只能和Buffer交互,因为Buffer,通道可以异步地读写

Selector(选择器)

NIO有选择器 而IO没有

  • 选择器用于使用单个线程处理多个通道,因此,他需要较少的线程来处理这些通道. 线程之间的切换对于操作系统来说是昂贵的,因此,为了提高系统效率选择器是有用的
  • 选择器Selector是NIO中的重要技术之一,它与SelectableChannel联合使用了非阻塞的多路复用,使用它可以节省CPU资源
  • 多路复用就是只需要一个线程就可以处理多个通道,降低内存占用率,减少CPU切换时间,在高并发,高频段的业务环境下由非常重要的优势
selector.open()  //创建一个Selector

为了能够让Channel和Selector配合使用,我们需要将Channel注册到Selector上,通过调用 channel.register() 方法来实现注册

channel.configureBlocking(false); //非阻塞
SelectionKey key=channel.register(selecotr.selevtionKey.OP_READ); //注册 

AIO (Asynchronous I/O)

AIO也就是NIO 2

Java 7 中引入了NIO的改进版 NIO2 它是异步非阻塞的IO模型, 异步IO是基于时事件和回调机制实现的,也就是应用操作之后会直接返回,不会堵塞在那里,当后台处理完成,操作系统会通知相应的线程进行后续操作

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值