处理 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 学习:服务端启动核心流程源码说明
- 七宝镇有什么好玩的