
基于前文对 NIO Selector 事件循环机制、selectedKeys 集合特性及 key.cancel() 清理逻辑的讨论,selector.selectedKeys() 返回的集合不会自动清空。若不调用 iterator.remove(),会导致严重的逻辑错误和性能问题。一、核心原因:防止重复处理集合特性:selector.selectedKeys() 是一个累积集合。每次 select() 方法发现就绪通道时,会将对应的 SelectionKey 添加到该集合中,而不是替换。后果:若不移除,下一次循环时,该键依然存在于集合中。即使该通道已无新事件,代码仍会再次执行 isAcceptable 或 isReadable 判断。对于读事件:可能导致对同一批数据重复处理,或因读取返回 0 而陷入死循环。对于接受事件:可能导致重复调用 accept(),引发异常或逻辑混乱。二、代码对比说明❌ 错误做法(未 remove)SetSelectionKeykeys=selector.selectedKeys();for(SelectionKeykey:keys){// 或使用 iterator 但不 removeif(key.isReadable()){// 第一次循环:处理数据}// 第二次循环:key 仍在集合中,再次进入此分支!}// 下次 select() 后,旧 key 和新 key 混在一起,全部被处理✅ 正确做法(必须 remove)IteratorSelectionKeyiterator=selector.selectedKeys().iterator();while(iterator.hasNext()){SelectionKeykey=iterator.next();iterator.remove();// 1. 立即从当前就绪集合中移除if(key.isReadable()){// 仅在本次事件中处理一次