使用java.nio,必须通过SelectableChannel注册对操作的兴趣:
SelectionKey = SelectableChannel.register(selector, interestInOpsBitmask)
注册兴趣:
取消注册兴趣:
有没有专业人士和缺点
由于
答案 0 :(得分:3)
我会按照您的建议使用or-operator更新现有的interestOps。如果我(暂时)取消选择键,我会担心缺少选择。
此外,取消+重新注册似乎比更新更复杂。
除非您有注册新操作的基本逻辑原因,否则我建议您始终使用更新。
答案 1 :(得分:3)
如果在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.
}
Firt执行几乎不会返回键,但是循环结束时的select() MAY 可以保证取消键的通道从选择器中取消注册(由你的impl决定) 。
但是,如果您只是在同一个线程中执行任务,那么您可以听取选择器事件,更新声音更容易,更安全。