JAVA NIO
NIO
- 每个channel都会对应一个buffer
- selector对应一个线程一个线程对应多个channel
- 改图反映三个channel注册到改selector程序
- 程序切换到哪个channel是由事件决定的,Event就是一个重要的概念
- Selector会根据不同的事件,在各个通道上切换
- Buffer就是一个内存块,底层是有一个数组
- 数据的读写都是通过Buffer,可以双向读写,需要flip方法切换
- channel是双向的,可以返回底层操作系统的情况,比如Linux,底层操作系统通道也是双向的
缓冲区(Buffer)
基本介绍
缓冲区(buffer):缓冲区的本质是一个可以读写数据的内存块,可以理解成是一个容器对象(含数组),该对象提供了一组方法,可以轻松地使用内存块,缓冲区对象内置了一些机制,能跟踪和记录缓冲区的状态变化情况。Channel提供文件、网络读取数据的渠道,但是读取或写入的数据都必须经由Buffer
Buffer类及子类
- Buffer是一个顶层父类,它是一个抽象类
- Buffer类定义了所有的缓冲区都有四个属性来提供关于其包含的数据元素
Capacity 容量,即可以容纳的最大数据量;在缓冲区创建时被设定且不能改变
Limit 表示缓冲区的当前终点,不能对缓冲区超过极限位置进行读写操作。且极限是可以修改的。
Position 位置,下一个要被读写的元素的索引。每次读写缓冲区数据都会改变值,为下次读写做准备
Mark 标记
通道(Channel)
- NIO的通道类似于流,但有如下区别:
- 通道可以同时进行读写,而流只能读或者只能写
- 通道可以实现异步读写数据
- 通道可以从缓冲中读数据,也可以写数据到缓冲中
- BIO中的stream是单向的,例如FileInputStream对象只能进行读取数据的操作,而NIO中的通道(Channel)是双向的,可以读操作也可以写操作
- Channel在NIO中是一个接口public interface Channel extends Closeable{}
- 常用的Channel类有:FileChannel、DatagramChannel、SocketChannel
- FileChannel用于文件数据的读写,DatagramChannel用于UDP的数据读写 ServerSocketChannel和SocketChnnnel用于TCP的读写
选择器(Selector)
- Java的NIO,用非阻塞的IO方式。可以用一个线程,处理多个的客户端连接,就会使用到Selector
- Selector能够检测多个注册的通道上是否有事件发送(多个Channel以事件的方式可以注册到同一个Selector)
如果有事件发生,便获取事件然后针对每个事件进行相应的处理,这样就可以用一个单线程去管理多个通道,也就是管理多个连接和请求。
- 只有在连接真正有读写发生时,才会进行读写,就大大地减少了系统开销,并且不必为每一个连接都创建一个线程,不用去维护多个线程
- 避免了多线程之间的上下文切换导致的开销
selector类相关方法
public static Selector open(); //得到一个选择器对象
public int Select(long timeout);//监控所有注册的通道,当其中有IO操作可以进行,将对应的SelectionKey加入到内部集合并返回,参数用来设置超时事件
public Set<SelectionKey>selectedKeys;//从内部集合中得到所有SelectionKey
SelectionKey
- SelectionKey,表示SelectionKey和网络通道的注册关系,共四种:
int OP_ACCEPT: 有新的网络连接可以accept,值为16
int OP_CONNECT: 表示连接已经建立,值为8
int OP_READ: 代表读操作,值为1
int OP_WRITE: 代表写操作,值为4
- SelectionKey的相关方法
Selector selector(); //得到与之关联的Selector对象
SelectableChannel channel(); //得到与之关联的通道
Object attachment(); //得到与之关联的共享数据
SelectionKey interestOps(int ops);//设置或改变监听事件
boolean isAcceptable();//是否可accept
boolean isReadable();//是否可读
boolean isWritable();//是否可写
ServerSocketChannel
- ServerSocketChannel在服务器监听新的客户端Socket连接
- 相关方法如下
ServerSocketChannel open();//得到一个ServerSocketChannel通道
ServerSocketChannel bind(SocketAddress local);//设置服务器端口端口号
ServerSocketChannel configureBlocking(boolean block);//设置阻塞或非阻塞模式
SelectionKey register(Selector sel,int ops);//注册一个选择器并设置监听事件
SocketChannel
- SocketChanel,网络IO通道,具体负责进行读写操作。NIO把缓冲区的数据写入通道,或者把通道的数据读到缓冲区。
- 相关方法如下
SocketChannel open(); //得到一个SocketChannel通道
SocketChannel configureBlocking(boolean block);//设置阻塞或非阻塞模式
connect(SocketAddress remote);//连接服务器
boolean finishConnect();//如果上面的方法连接失败,接下来就要通过该方法完成连接操作
int write(ByteBuffer src);//往通道里写数据
int read(ByteBuffer dst);//往通道里读数据

浙公网安备 33010602011771号