网站 用什么数据库/搜索引擎营销的主要模式有哪些
Selector
Selector 一般称 为选择器 ,也可称为 多路复用器 。它是Java NIO核心组件中的一个,用于检查一个或多个NIO Channel(通道)的状态是否处于可读、可写。如此可以实现单线程管理多个channels,也就是可以管理多个网络链接。
一个通道在Selector上注册了,就生成了一个SelectionKey
使用Selector的好处在于: 使用更少的线程来就可以来处理通道了, 相比使用多个线程,避免了线程上下文切换带来的开销。
Selector的继承实现框图如下:
源码如下:
public abstract class Selector implements Closeable {/*** 构造方法*/protected Selector() { }/*** 静态方法,开启一个selector*/public static Selector open() throws IOException {return SelectorProvider.provider().openSelector();}/*** 判断selector是否开启*/public abstract boolean isOpen();/*** 返回创建通道的provider*/public abstract SelectorProvider provider();/*** selector上面注册的通道数keys不可直接修改。密钥只有在被取消并且其通道被取消注册后才能被删除。*/public abstract Set<SelectionKey> keys();/*** 返回此选择器的选定键集。* 某通道上的事件数目*/public abstract Set<SelectionKey> selectedKeys();/*** 选择一组键,这些键对应的通道已准备好进行I/O操作。*/public abstract int selectNow() throws IOException;/*** 选择一组键,这些键对应的通道已准备好进行I/O操作设置时间,timeout如果为正,则在等待通道准备就绪时阻塞最多timeout毫秒(或多或少);如果为零,则无限期阻塞;不得为负*/public abstract int select(long timeout)throws IOException;/*** 选择一组键,这些键对应的通道已准备好进行I/O操作*/public abstract int select() throws IOException;/*** 使尚未返回的第一个选择操作立即返回。*/public abstract Selector wakeup();/*** 关闭选择器*/public abstract void close() throws IOException;}
SelectorImpl
selector的实现类,主要完成一些基本的方法,一些方法的具体实现由其子类WindowsSelectorImpl进行实现
public abstract class SelectorImpl extends AbstractSelector {// 设置一些SelectionKeyprotected Set<SelectionKey> selectedKeys = new HashSet(); // 通道上面的事件数protected HashSet<SelectionKey> keys = new HashSet(); // 在selector上注册的通道数private Set<SelectionKey> publicKeys;private Set<SelectionKey> publicSelectedKeys;protected SelectorImpl(SelectorProvider var1) {super(var1);if (Util.atBugLevel("1.4")) {this.publicKeys = this.keys;this.publicSelectedKeys = this.selectedKeys;} else {this.publicKeys = Collections.unmodifiableSet(this.keys);this.publicSelectedKeys = Util.ungrowableSet(this.selectedKeys);}}/*** 获取通道的数目*/public Set<SelectionKey> keys() {if (!this.isOpen() && !Util.atBugLevel("1.4")) {throw new ClosedSelectorException();} else {return this.publicKeys;}}/*** 获取通道上面的事件数目*/public Set<SelectionKey> selectedKeys() {if (!this.isOpen() && !Util.atBugLevel("1.4")) {throw new ClosedSelectorException();} else {return this.publicSelectedKeys;}}/*** 选择一组键,这些键对应的通道已准备好进行I/O操作阻塞到至少有一个通道在你注册的事件上就绪了。*/public int select() throws IOException {return this.select(0L);}/*** 选择一组键,这些键对应的通道已准备好进行I/O操作*/public int select(long var1) throws IOException {if (var1 < 0L) {throw new IllegalArgumentException("Negative timeout");} else {return this.lockAndDoSelect(var1 == 0L ? -1L : var1);}}// 其实与select的功能是一样的,只不过select0通过select(long var1)传入lockAndDoSelect后,其值变为了-1,而selectNow直接就是传入// 非阻塞,只要有通道就绪就立刻返回。public int selectNow() throws IOException {return this.lockAndDoSelect(0L);}/*** 加锁并且进行已准备I/0操作的通道选择*/private int lockAndDoSelect(long var1) throws IOException {synchronized(this) {if (!this.isOpen()) {throw new ClosedSelectorException();} else {int var10000;// 进行加锁synchronized(this.publicKeys) {synchronized(this.publicSelectedKeys) {// 调用子类的select方法var10000 = this.doSelect(var1);}}return var10000;}}}// 由子类进行实现protected abstract int doSelect(long var1) throws IOException;// 通道注册入selector生成SelectionKeyprotected final SelectionKey register(AbstractSelectableChannel var1, int var2, Object var3) {if (!(var1 instanceof SelChImpl)) {throw new IllegalSelectorException();} else {SelectionKeyImpl var4 = new SelectionKeyImpl((SelChImpl)var1, this);// 第三个变量就作为SelectionKey的Attachmentvar4.attach(var3);synchronized(this.publicKeys) {this.implRegister(var4);}var4.interestOps(var2);return var4;}}// 由子类进行实现protected abstract void implRegister(SelectionKeyImpl var1);// 关闭selector的实现方法,加锁进行实现public void implCloseSelector() throws IOException {this.wakeup();synchronized(this) {synchronized(this.publicKeys) {synchronized(this.publicSelectedKeys) {this.implClose();}}}}// 由子类进行实现protected abstract void implClose() throws IOException;public void putEventOps(SelectionKeyImpl var1, int var2) {}void processDeregisterQueue() throws IOException {Set var1 = this.cancelledKeys();synchronized(var1) {if (!var1.isEmpty()) {Iterator var3 = var1.iterator();while(var3.hasNext()) {SelectionKeyImpl var4 = (SelectionKeyImpl)var3.next();try {this.implDereg(var4);} catch (SocketException var11) {throw new IOException("Error deregistering key", var11);} finally {var3.remove();}}}}}// 由子类进行实现protected abstract void implDereg(SelectionKeyImpl var1) throws IOException;// 由子类进行实现,让处在阻塞状态的select()方法立刻返回public abstract Selector wakeup();
}
SelectionKey
一个通道在Selector上注册后就会生成一个SelectionKey
public abstract class SelectionKey {protected SelectionKey() { }/*** SelectionKey关联的channel*/public abstract SelectableChannel channel();/*** SelectionKey关联的selector*/public abstract Selector selector();/*** 判断这个key是否是有效的*/public abstract boolean isValid();/*** 请求取消此key的通道与其选择器的注册。*/public abstract void cancel();/*** 检索此键的兴趣集。*/public abstract int interestOps();/*** 将此键的兴趣集设置为给定值。*/public abstract SelectionKey interestOps(int ops);/*** 检索此密钥的就绪操作集。*/public abstract int readyOps();/*** 操作-读*/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;/*** 是否可读*/public final boolean isReadable() {return (readyOps() & OP_READ) != 0;}/*** 是否可写*/public final boolean isWritable() {return (readyOps() & OP_WRITE) != 0;}/*** 是否可连接*/public final boolean isConnectable() {return (readyOps() & OP_CONNECT) != 0;}/*** 是否可接收*/public final boolean isAcceptable() {return (readyOps() & OP_ACCEPT) != 0;}// key的附加private volatile Object attachment = null;private static final AtomicReferenceFieldUpdater<SelectionKey,Object>attachmentUpdater = AtomicReferenceFieldUpdater.newUpdater(SelectionKey.class, Object.class, "attachment");/*** 将给定对象附加到该key*/public final Object attach(Object ob) {return attachmentUpdater.getAndSet(this, ob);}/*** 返回该key附加的对象*/public final Object attachment() {return attachment;}}
SelectionKeyImpl
SelectionKey的实现类
public class SelectionKeyImpl extends AbstractSelectionKey {final SelChImpl channel;public final SelectorImpl selector;private int index;private volatile int interestOps;private int readyOps;SelectionKeyImpl(SelChImpl var1, SelectorImpl var2) {this.channel = var1;this.selector = var2;}// 返回channelpublic SelectableChannel channel() {return (SelectableChannel)this.channel;}// 返回selectorpublic Selector selector() {return this.selector;}int getIndex() {return this.index;}void setIndex(int var1) {this.index = var1;}// 确认是否有效private void ensureValid() {if (!this.isValid()) {throw new CancelledKeyException();}}// 获取监听事件public int interestOps() {this.ensureValid();return this.interestOps;}// 设置或者改变监听的事件public SelectionKey interestOps(int var1) {this.ensureValid();return this.nioInterestOps(var1);}public int readyOps() {this.ensureValid();return this.readyOps;}public void nioReadyOps(int var1) {this.readyOps = var1;}public int nioReadyOps() {return this.readyOps;}public SelectionKey nioInterestOps(int var1) {if ((var1 & ~this.channel().validOps()) != 0) {throw new IllegalArgumentException();} else {this.channel.translateAndSetInterestOps(var1, this);this.interestOps = var1;return this;}}public int nioInterestOps() {return this.interestOps;}
}
具体使用的demo见github,地址如下:
netty-stdudy