欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  数据库

深入解析MapReduce架构设计与实现原理–读书笔记(8)hadoop NIO

程序员文章站 2024-01-29 19:55:34
...

J2SE1.4以后, java 发布了新的IO类库,简称NIO。引入了全新的高效的IO机制,同时引入了基于Reactor设计模式的多路复用异步模式。 包含以下几种抽象数据类型 Channel(管道) NIO把它支持的IO对象抽象为channel。它模拟了通信连接,类似于IO中的stream。用户可

J2SE1.4以后,java发布了新的IO类库,简称NIO。引入了全新的高效的IO机制,同时引入了基于Reactor设计模式的多路复用异步模式。

包含以下几种抽象数据类型

Channel(管道)

NIO把它支持的IO对象抽象为channel。它模拟了通信连接,类似于IO中的stream。用户可以通过它读取和写入数据。
SocketChannel,ServerSocketChannel,FileChannel,DatagramChannel等。

Buffer(缓冲区)

Buffer是一块连续的内存区域,一般作为channel收发数据的载体出现。所有数据都通过Buffer对象来处理。用户永远不会将字节直接写入channel中。
相反,需要将数据写入包含一个或者多个字节的缓冲区;同样,也不会直接从通道中读取字节,而是将数据从通道读入缓冲区,再从缓冲区获取这个字节。

Selector(选择器)

Selector类提供了监控一个或者多个channel当前状态的机制。只要Channel向Selector注册了某种特定事件,Selector就会监听这些事件是否会发生,一旦发生某个事件,
便会通知对应的Channel。

常用类

1.Buffer相关类

java.nio包公开了Buffer API,可以直接控制和运用缓冲区。所有缓冲区包含以下3个属性
capacity:缓冲区的末位值。它表明了缓冲区最多可以保存多少数据。
limit:表示缓冲区的的那个钱存放数据的终点,不能对超过limit的区域进行读写操作
position:下一个读写单元的位置。每次读写缓冲区时,均会修改该值,为下一次读写数据做准备。
capacity>=limit>=position>=0
buffer有2种工作模式:写模式和读模式。
写模式下,limit与capacity相同,position随着写入数据增加,逐渐增加到limit,因此,0到position之间的数据即为已经写入的数据。
读模式下,limit初始指向position所在位置,position随着数据的读取,逐渐增加到limit,则0到position之间的数据即为已经读取的数据。
flip() 可将写模式转换为读模式
clear() 重置Buffer,即将limit设为capacity,而position为0
hasRemaining()/remaining() 分别用于判断Buffer是否有剩余空间和获取Buffer剩余空间。剩余空间大小为capacity – position
capacity()/limit()/position() 分别用于获取属性值。
limit(int newLimit)/position(int newPosition) 分别用于设置Buffer的limit和position属性。
java.nio.buffer是一个抽象类,不能被实例化。每种基本类型都有对应的具体的Buffer类(除boolean)。其中最基本的是ByteBuffer。它存放的数据单元是字节。
它并没有提供直接的构造函数,而提供了静态方法。
//创建一个Heap Buffer,其空间分配在JVM的堆上,由GC回收。
static ByteBuffer allocate(int capacity) ;
//创建一个Direct Buffer,通过底层的JNI调用C Runtime Time的malloc函数分配空间,可看作内核空间。创建代价大,但是比Heap Buffer更高效。
static ByteBuffer allocateDirect(int capacity);

2.channel相关类

java.nio提供了多种Channel实现,其中,最常用的是以SelectableChannel为基类的通道。支持阻塞IO与非阻塞IO。
//设置当前SelectableChannel的阻塞模式;block表示是否将SelectableChannel设置为阻塞模式;返回SelectableChannel对象本身的引用。
SelectableChannel configureBlocking(boolean block) throws IOException
//将当前Channel注册到一个Selector中,sel表示要注册的Selector,ops表示注册事件。
//ops包括:OP_READ,OP_ACCEPT,OP_WRITE,OP_CONNECT
SelectionKey register(Selector sel,int ops) throws ClosedChannelException
包含2个子类
ServerSocketChannel,SocketChannel,他们分别是ServerSocket和Socket的替代类。
ServerSocketChannel用于监听TCP连接
ServerSocketChannel open() throws IOException;//创建ServerSocketChannel的静态工厂方法。
SocketChannel accept() throws IOException;//接收来自客户端的连接。一旦有客户端请求出现,则会返回一个处于阻塞模式的SocketChannel
ServerSocket socket() 返回一个与ServerSocketChannel关联的ServerSocket对象。
SocketChannel可以看作Socket的替代类。
boolean connect(SocketAddress remote) throws IOException //连接Channel对应的Socket。如果SocketChannel处于阻塞状态,直接返回结果;否则,进入阻塞状态。
//将当前channel中的数据读取到ByteBuffer中。在非阻塞模式中,能读取到多少数据就读取多少的原则,总是立即返回结果;
//在阻塞模式下,将尝试一直读取数据,知道ByteBuffer被填满,到达输入流末尾或者抛出异常。该函数的返回值为实际读取的数据字节数。
int read(ByteBuffer dst) throws IOException
//将ByteBuffer中的数据写入Channel中。与read函数类似。
//在非阻塞模式下,能输出多少数据就输出多少的原则,总是立即返回结果;
//在阻塞模式下,会尝试将所有数据写入channel。
int write(ByteBuffer src) throws IOException

3.Selector类

Selector可监听ServerSocketChannel和SocketChannel注册的特定事件,一旦某个事件发生,则会通知对应的Channel。SelectableChannel的register方法负责注册事件。
该方法返回一个SelectionKey对象,该对象即为用于跟踪这些注册事件的句柄。
//静态工厂,创建Selector对象。
static Selector open()
//该方法等待并返回发生的事件。一旦某个注册的事件发生,就会返回对应的SelectionKey的数目。
int select(long timeout)
//Selector捕获的已经发生事件对应的SelectionKey集合。
set SelectedKeys()

4.SelectionKey类

ServerSocketChannel或SocketChannel通过register()方法向Selector注册事件时,regsiter方法就会创建一个SelectionKey对象,用于跟踪注册事件。
SelectionKey.OP_ACCEPT:接收连接就绪事件,表示服务器端接收到了客户端连接。
SelectionKey.OP_CONNECT:连接就绪事件,表示客户端与服务器端的连接已经建立成功。
SelectionKey.OP_READ:读就绪事件,表示通道中已经有了可读数据,可执行读操作了。
SelectionKey.OP_WRITE:写就绪事件,表示可向通道中写入数据了。
通常,ServerSocketChannel对象向Selector中注册OP_ACCEPT事件;SocketChannel对象向Selector中注册OP_CONNECT,OP_READ,OP_WRITE三种事件。
//为当前SelectionKey关联一个Object类型的对象。每个SelectionKey只能关联一个对象。
Object attach(Object obj);
//获取当前SelectionKey关联的Object对象
Object attachment();
//返回与当前SelectionKey关联的SelectableChannel对象
SelectableChannel channel();