某个SelectionKey处理完之后,怎么避免下次循环重复处理
来源:7-10 NIO服务器Thread优化-4
向松__
2018-11-14
我看老师的逻辑是每处理一个SelectionKey,都要取消一次,然后下次读取的时候都重新调用key.interestOps继续监听。这样是可避免重复处理,但是这样的同步操作,重复的多了也不太好吧。
以下是老师的取消注册代码:
private static void handleSelection(SelectionKey key, int keyOps,
HashMap<SelectionKey, Runnable> map,
ExecutorService pool) {
// 重点
// 取消继续对keyOps的监听
key.interestOps(key.readyOps() & ~keyOps);
Runnable runnable = null;
try {
runnable = map.get(key);
} catch (Exception ignored) {
}
if (runnable != null && !pool.isShutdown()) {
// 异步调度
pool.execute(runnable);
}
}
但是我查了一些资料,大部分是通过以下方式避免重复处理的:
Set selectedKeys = selector.selectedKeys();
Iterator it = selectedKeys.iterator();
while (it.hasNext()) {
SelectionKey key = (SelectionKey)it.next();
// ... deal with I/O event ...
it.remove(); //调用迭代器的 remove() 方法来删除处理过的 SelectionKey
}
写回答
1回答
-
我可以100%的明确的告诉你 你百度到的代码有问题,不信你可以试试运行一下。
用一个客户端给他发送消息,持续发送,同时在处理io的位置使用多线程异步处理。
100%会出现多线程任务队列加入一大堆的任务进去。而且都是一个客户端的读取,到时候多线程并发也会导致读取数据错乱。
你百度的版本不适合多线程使用,说白了,处理部分逻辑如果是同步处理,也就是同时有3个客户端来消息了,他需要一个个读取,然后再读取下一个的,而且他没有移除监听,只是移除了本次的状态而已。
他这个对于客户端量少来说没啥问题,多了,并且同时来消息时只能一个读取了再读取下一个,会消耗很多时间,不能发挥多线程的优势。
而我那边那个自然也有性能问题,但是两者对比起来更优,我的方案也是mina的早期做法。
后面12章节会讲解这个部分优化。
242019-07-16
相似问题