外贸网站建设公司/中国重大新闻
目录
Selector模型
SelectableChannel
Channel注册到Selector
SelectionKey
遍历SelectionKey
事件驱动
责任链模式
Selector模型
Java NIO是基于Selector模型来实现非阻塞IO,Netty底层基于Java NIO实现的,因此也使用了Selector模型。
Selector提供了选择执行已经就绪的任务的能力。从底层看,Selector会轮询Channel是否已经准备好执行每个IO操作。Selector允许单个线程处理多个Channel。
SelectableChannel
并不是所有的Channel都是可以被Selector复用的,只有抽象类SelectableChannel的子类才能被Selector复用。FileChannel就不能被复用,因其不是SelectableChannel的子类。
SelectableChannel并发安全。
Channel注册到Selector
/* *Registers this channel with the given selector, returning a selection* key.*@param sel* The selector with which this channel is to be registered** @param ops* The interest set for the resulting key** @param att* The attachment for the resulting key; may be <tt>null</tt>
**/
public final SelectionKey register(Selector sel, int ops)
public abstract SelectionKey register(Selector sel, int ops, Object att)
可供Selector查询的通道操作主要有四种:
public static final int OP_READ = 1 << 0;
public static final int OP_WRITE = 1 << 2;
public static final int OP_CONNECT = 1 << 3;
public static final int OP_ACCEPT = 1 << 4;
- 某个SocketChannel通道可以连接到一个服务器,则处于OP_CONNECT状态
- 一个ServerSocketChannel服务器通道准备好接收新接入的连接,则处于OP_ACCEPT状态
- 一个有数据可读的Channel,OP_READ状态
- 一个等待写数据的通道,OP_WRITE状态
SelectionKey
Channel和Selector关系确定好之后,一旦Channel处于某种就绪状态,就可以被选择器查询到,使用Selector.select()方法。
获取感兴趣的事件集合:
public abstract int interestOps();
获取通道已经准备就绪的操作的集合:
public abstract int readyOps();
从SelectionKey访问Channel和Selector:
selectionKey.channel();
selectionKey.selector();
可以将一个对象或其他信息附着到SelectionKey上:
selectionKey.attach(theObject);
selectionKey.attachment();
channel.register(selector, SelectionKey.OP_READ, theObject)
遍历SelectionKey
Selector selector = Selector.open();ByteBuffer buffer = ByteBuffer.allocate(16);ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();serverSocketChannel.configureBlocking(false);serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);serverSocketChannel.bind(new InetSocketAddress(8080));while (true) {selector.select();Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();while (iterator.hasNext()) {SelectionKey selectionKey = iterator.next();if(selectionKey.isAcceptable()) {ServerSocketChannel channel = (ServerSocketChannel) selectionKey.channel();SocketChannel socketChannel = channel.accept();socketChannel.configureBlocking(false);socketChannel.register(selector, SelectionKey.OP_READ);}if(selectionKey.isReadable()) {SocketChannel channel = (SocketChannel) selectionKey.channel();channel.read(buffer);buffer.flip();ByteBufferUtil.debugAll(buffer);buffer.clear();}iterator.remove();}}
每次迭代记得调用iterator.remove。
事件驱动
Netty是异步的事件驱动网络应用框架。