事件驱动模型的角度来看看 JAVA NIO
2016-02-11 00:51
597 查看
事件驱动模型的角度来看看 JAVA NIO
事件驱动模型的角度来看看 java nio,先作知识的简单铺垫,1,阻塞非阻塞
阻塞式I/O模型:
(1)等待数据准备好;
(2)从内核向进程复制数据。
2,非阻塞式I/O: 当所请求的I/O操作非得把本进程投入睡眠才能完成时,不要把进程投入睡眠,而是返回一个错误。进而不断的通过轮询方式来获取正确的结果
3,I/O多路复用:虽然I/O多路复用的函数也是阻塞的,但是其与以上两种还是有不同的,I/O多路复用是阻塞在select,epoll这样的系统调用之上,而没有阻塞在真正的I/O系统调用。
阻塞,非阻塞:进程/线程要访问的数据是否就绪,进程/线程是否需要等待;
同步,异步:访问数据的方式,同步需要主动读写数据,在读写数据的过程中还是会阻塞;异步只需要I/O操作完成的通知,并不主动读写数据,由操作系统内核完成数据的读写。
这里只是简单的概述而已
4.nio 主要模块介绍
selector 主要负责监听io事件,channel这里可以简单理解对于数据的操作,我觉得把它理解为socket 吧好理解一点,比如发送数据和读取数据,buffer 则是将数据进行读入和读取,对于buffer的理解可以参照java io 读取的文件的buffer
5,java nio 开发流程架构
6,代码的实现:
(1)Reactor 构造函数
public Reactor(int port) throws IOException { selector = Selector.open(); serverSocketChannel = ServerSocketChannel.open(); serverSocketChannel.bind(new InetSocketAddress(port)); serverSocketChannel.configureBlocking(false); SelectionKey selectionKey = serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT); selectionKey.attach(new Acceptor()); }
Reactor是一种事件驱动模型;使用Selector 有如下方法
a. public static Selector open();
该方法获取一种io 多路复用的机制,比如linux 2.6+平台java提供的是epoll 机制,mac os x 提供的是kqueue机制,这里就不对io 复用探讨
b. 获取server channel 对象进行绑定监听端口
c. 设置服务方式为非阻塞方式
d. 将channel 注册到selector 上,让selector 去管理我们关心的io
e. SelectionKey 理解为selector 和 channel 之间的抽象
(2)实现Runable接口的run 方法
public void run() { try { while (!Thread.interrupted()) { selector.select(); Set selected = selector.selectedKeys(); Iterator it = selected.iterator(); //循环的遍历,可以操作的事件 while (it.hasNext()) //将读取到的事件进行分发 dispatch((SelectionKey)(it.next())); selected.clear(); } } catch (IOException e){ } }
Selector是java nio 中的多路复用器,配合SelectionKey使用,SelectionKey代表着一个Channel和Selector的关系的抽象,Channel向Selector注册的时候产生,由Selector维护。Selector维护着三个SelectionKey的集合:
private Set publicKeys; 当有SelectionKey关联的Channel有Channel向Selector注册的IO事件就绪的时候并且有select操作,对应的SelectionKey会被放到publicSelectedKeys中。因为这个集合中的SelectionKey可以通过直接调用Set的remove将SelectionKey移除。
private Set publicSelectedKeys 当有SelectionKey关联的Channel有Channel向Selector注册的IO事件就绪的时候并且有select操作,对应的SelectionKey会被放到publicSelectedKeys中。因为这个集合中的SelectionKey可以通过直接调用Set的remove将SelectionKey移除。
private final Set cancelledKeys 当有已经向Selector注册的Channel发生degistered的时候,SelectionKey将被放到这个集合,并且在下一次select的时候被从所有的集合中移出。
(3)Acceptor 类:
class Acceptor implements Runnable { public void run() { try { SocketChannel c = serverSocketChannel.accept(); if (c != null) new Thread(new Handler(c,selector)).start(); } catch(IOException ex) { } } }
这里就是获取到相应的channel 对象,然后交给处理线程 handler去处理
(4)dispatch 方法:
private void dispatch(SelectionKey k) { Runnable r = (Runnable)(k.attachment()); if (r != null) r.run(); }
这里 SelectionKey .attachment 使用的是AtomicReferenceFieldUpdater 这个类的方法 原子更新
(5)Handler 类
public Handler(SocketChannel socketChannel, Selector selector) throws IOException { this.socketChannel = socketChannel; socketChannel.configureBlocking(false); selectionKey = socketChannel.register(selector, 0); selectionKey.attach(this); selectionKey.interestOps(SelectionKey.OP_READ); selector.wakeup(); } public void run() { if (state == READING) read(); else if (state == SENDING) send(); }
逻辑,就是让selector 继续侦听我们注册的事件,然后对于数据进行read write 操作而已
代码地址
至此整个reactor 的基本架构已经结束,此次纪录为后面的netty 做准备
相关文章推荐
- java对世界各个时区(TimeZone)的通用转换处理方法(转载)
- java-注解annotation
- java-模拟tomcat服务器
- java-用HttpURLConnection发送Http请求.
- java-WEB中的监听器Lisener
- Android IPC进程间通讯机制
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- 介绍一款信息管理系统的开源框架---jeecg
- 聚类算法之kmeans算法java版本
- java实现 PageRank算法
- PropertyChangeListener简单理解
- spymemcached源码中Reactor模式分析
- c++11 + SDL2 + ffmpeg +OpenAL + java = Android播放器
- 插入排序
- 冒泡排序
- 堆排序
- 快速排序