处理 IO 事件的 Channel调用的是NioEventLoop
的如下方法
private void processSelectedKeys() { if (selectedKeys != null) { // 处理优化过的 SelectedKeys processSelectedKeysOptimized(); } else { // 处理正常的 SelectedKeys processSelectedKeysPlain(selector.selectedKeys()); } }上述两个分支分别处理了不同类型的 key:重点关注优化过的 SelectedKeys,selectedKeys 在 NioEventLoop 中是一个SelectedSelectionKeySet
对象,这个对象虽然叫Set
, 但是底层使用了数组
final class SelectedSelectionKeySet extends AbstractSet<SelectionKey> { SelectionKey[] keys; int size; SelectedSelectionKeySet() { keys = new SelectionKey[1024]; } @Override public boolean add(SelectionKey o) { if (o == null) { return false; } keys[size++] = o; if (size == keys.length) { increaseCapacity(); } return true; } ......}add 方法的主要流程是:
- 将SelectionKey塞到该数组的尾部;
- 更新该数组的逻辑长度+1;
- 如果该数组的逻辑长度等于数组的物理长度,就将该数组扩容 。
O(1)
的时间复杂度就能将SelectionKey
塞到set
中去,而 JDK 底层使用的HashSet , put的时间复杂度最少是O(1),最差是O(n) 。进入
processSelectedKeysOptimized
方法private void processSelectedKeysOptimized(SelectionKey[] selectedKeys) { for (int i = 0;; i ++) { final SelectionKey k = selectedKeys[i]; if (k == null) { break; } // null out entry in the array to allow to have it GC'ed once the Channel close // See https://github.com/netty/netty/issues/2363 selectedKeys[i] = null; final Object a = k.attachment(); if (a instanceof AbstractNioChannel) { processSelectedKey(k, (AbstractNioChannel) a); } else { @SuppressWarnings("unchecked") NioTask<SelectableChannel> task = (NioTask<SelectableChannel>) a; processSelectedKey(k, task); } if (needsToSelectAgain) { // null out entries in the array to allow to have it GC'ed once the Channel close // See https://github.com/netty/netty/issues/2363 for (;;) { i++; if (selectedKeys[i] == null) { break; } selectedKeys[i] = null; } selectAgain(); // Need to flip the optimized selectedKeys to get the right reference to the array // and reset the index to -1 which will then set to 0 on the for loop // to start over again. // // See https://github.com/netty/netty/issues/1523 selectedKeys = this.selectedKeys.flip(); i = -1; } } }
推荐阅读
- ZCTF note3:一种新解法
- 学习ASP.NET Core Blazor编程系列四——迁移
- 五 Netty 学习:服务端启动核心流程源码说明
- 【前端必会】走进webpack生命周期,另类的学习方法
- opencvcv.line
- 骰子五个点怎么玩(骰子五个六五个七怎么玩)
- 三十六 Java开发学习----SpringBoot三种配置文件解析
- 4 MySQL学习---MySQL索引
- 基础&进阶 线段树学习笔记(一) | P3372 【模板】线段树 1 题解
- 王者荣耀七周年击败特效怎么领取