JAVA IO模型和NIO概念
IO表示 input/output,Java的 IO 帮助我们可以从文件、网络、内存等地方读取和写入数据。
Java io 是以流为基础进行输入输出的,程序—数据流—数据源,数据源可以是文件、内存、网络等,数据通过数据流来到程序内存中,我们可以对其进行处理。
A. IO 模型
- 阻塞IO模型
- 非阻塞IO模型
- 多路复用IO模型
- 信号驱动IO模型
- 异步IO模型
阻塞IO模型
最传统的IO模型。内核一直处于等待状态直到数据就绪,在等待期间线程处于阻塞状态。当数据就绪之后,用户线程去读写并解除block状态。这样一来,如果数据迟迟没有就绪,内核就一直处于等待状态,程序的效率将会大大降低。
就比如在A同学在聊微信,在等待对方回应后才进行下一条消息的发送,在等待对方回应期间什么事情也不做,就对着屏幕发呆直到收到对方的消息。
有一个典型的阻塞IO的例子就是socket的read()方法,如果端口没有收到数据,就会一直阻塞在read()方法。
非阻塞IO模型
非阻塞IO模型不需要像阻塞IO模型一样坐在那里干等,用户线程会不断地询问内核数据是否准备就绪,如果没有那就待会再来问一次,如果就绪的话就进行数据的读写。这样一来不会使内核一直处于等待状态,但是频繁地访问还是会给CPU带来一定的负担。
就比如还是A同学在聊微信,但是在等待对方消息的时候不再看着屏幕干等,而是过一会就看看手机对方有没有回消息,如果没有就待会再看一次,直到对方回微信为止。
多路复用IO模型
多路复用是目前使用比较多的模型,在这个模型中,会创建一个线程专门去不断地轮询多个socket的状态,只要发现有就绪的数据,就进行读写。
就比如还是A同学在聊微信,这次同时用若干台手机和若干个对象聊微信,但这次A同学请了B助理来帮忙,B助理会不断地查看这若干个手机看是否有手机接收到消息。如果发现某个手机收到了回复,就通知A同学。
信号驱动IO模型
信号驱动模型,是指在数据就绪的时候,会通知用户线程,然后用户线程就进行相应的读写。
就比如还是A同学在聊微信,在微信收到回复的时候,手机会发出提示音来提醒A同学收到了消息,A同学就能知道自己收到了回复并进行操作。
异步IO模型
在异步IO模型中,内核在数据就绪的时候,会代替用户线程对数据进行读写操作,并在操作完成之后通知用户线程。也就是说,用户线程完全不需要去操心整个IO操作的过程,当收到内核的通知的时候,用户线程已经可以去直接使用读取到的数据了。
就比如还是A同学在聊微信,同学A发出信息后,不用自己去等回复,助理B代替A同学拿着手机,当助理B发现微信收到回复后,就帮A进行应答,A同学就不需要去操心了。
B. Java NIO概念
NIO有三大核心:
- Channel
- Buffer
- Selector
1. Channel 通道
channel和流差不多是一个意思,但是输入输出流是单向的,而channel是双向的,不仅可以进行写操作,也能进行读操作。
NIO主要有:
- 对应文件io的FileChannel
- 对应UDP的io通道DatagramChannel
- 以及对应TCP客户端和服务端的
- SocketChannel
- ServerSocketChannel
2. Buffer
Buffer是缓冲区,数据从通道想要到达目的地前要经过Buffer。例如从网络中读取的数据先是到达了Channel、然后经过Buffer才能到达client:
web – channel – buffer – client
3. Selector
Selector是NIO的重要的一个类。Channel会注册到selector上面,如果channel上有事件发生,那么就会获取这个事件并进行相应处理。相当于用一个线程去管理多个channel,不需要对每一个链接都开一个新的线程,避免了多线程切换时上下文的开销。