使用java.nio,必须通过SelectableChannel注册操作的兴趣:
SelectionKey = SelectableChannel.register(selector, interestInOpsBitmask)
Run Code Online (Sandbox Code Playgroud)
注册兴趣:
取消注册兴趣:
有任何利弊吗?
谢谢
如果您总是在 select() 返回后将执行分派给线程池,您可能希望立即取消该键,因为您失去了对 Runnable 执行时间的控制。
例如:如果在取消前一个键之前执行下一个 select()(线程仍在等待执行),则它仍然有效,导致另一个线程携带已经分派的键。如果这些线程之一取消了该密钥,则另一个线程除了引入意外行为之外还将收到CancelledKeyException异常。
即使您取消该密钥,线程也可能会在通道取消注册之前注册相同的通道(更新选择密钥)(由于您之前的原因key.cancel())。再次,什么会导致CancelledKeyException。
要摆脱这个陷阱,您可能希望始终在下一个循环中处理事件:
while (true) { // true or something less risky
//for each pendingTasks call
pool.execute(task);
Iterator<SelectionKey> iter = selector.selectedKeys().iterator();
while (iter.hasNext()) {
SelectionKey key = iter.next();
iter.remove();
key.cancel();
//store dispatch for the next while iteration
pendingTasks.add(task); // do not execute tasks before next select()
}
selector.select(TIMEOUT); // or selectNow if there are
//any pending events to handle.
}
Run Code Online (Sandbox Code Playgroud)
第一次执行几乎永远不会返回键,但是循环末尾的 select()可以保证取消键的通道从选择器中注销(由您的实现决定)。
但是,如果您只是在侦听选择器事件的同一线程中执行任务,则更新听起来既简单又安全。
| 归档时间: |
|
| 查看次数: |
5642 次 |
| 最近记录: |