归根到底,默认的 SelectorProvider 应该是 jdk nio 的 DefaultSelectorProvider 。
实际上,还是根据初始化 ServerSocketChannel:
public NioServerSocketChannel(ServerSocketChannel channel) { super(null, channel, SelectionKey.OP_ACCEPT); config = new NioServerSocketChannelConfig(this, javaChannel().socket());}
可以看到,这里默认注册监听了 SelectionKey.OP_ACCEPT 事件 。
其中 SelectionKey 只有 4 种:
public static final int OP_ACCEPT = 1 << 4;public static final int OP_CONNECT = 1 << 3;public static final int OP_WRITE = 1 << 2;public static final int OP_READ = 1 << 0;
NioserverSocketChannel 注册注册的源码比较多,看得人云里雾里的 。
可以理解,就是首先注册自己感兴趣的事件,发生的时候通知你即可 。
注册的方法如下我们主要看 NioEventLoop 即可,这个类继承自 SingleThreadEventLoop 类 。
实现了 SingleThreadEventExecutor 类的 run 方法,如下:
@Overrideprotected void run() { for (;;) { try { switch (selectStrategy.calculateStrategy(selectNowSupplier, hasTasks())) { case SelectStrategy.CONTINUE: continue; case SelectStrategy.SELECT: select(wakenUp.getAndSet(false)); if (wakenUp.get()) { selector.wakeup(); } // fall through default: } // 省略 processSelectedKeys(); // 省略 } catch (Throwable t) { handleLoopException(t); } // Always handle shutdown even if the loop processing threw an exception. // 省略 }}
我们只看核心的部分,这里实际上就是一个死循环,注册的部分核心如下:
public void register(final SelectableChannel ch, final int interestOps, final NioTask<?> task) { // 省略 ch.register(selector, interestOps, task); // 省略}
在 AbstractSelectableChannel 中的实现如下:
public final SelectionKey register(Selector sel, int ops, Object att) throws ClosedChannelException{ synchronized (regLock) { // 省略 SelectionKey k = findKey(sel); if (k != null) { k.interestOps(ops); k.attach(att); } if (k == null) { // New registration synchronized (keyLock) { if (!isOpen()) throw new ClosedChannelException(); k = ((AbstractSelector)sel).register(this, ops, att); addKey(k); } } return k; }}
推荐阅读
- Netty 实战:如何实现文件服务器?
- Netty 实战:如何实现 HTTP 服务器?
- 什么是2021年最佳的后端开发框架
- 如何实现几百台SIP终端实现自动化部署
- 如何在 Linux 终端查看图像
- 浅谈linux下基于UDP服务的负载均衡方法
- 粽子是端午节的必备食物据说在春秋时期 关于端午粽子的由来
- 端午节五彩线的颜色 端午节绑五色线的意义
- 驱五毒是什么节日 端午节的五毒有哪些
- 课后服务申请理由怎么写?