gpt4 book ai didi

java - NIO 最佳实践——SelectableChannel 和 InterestOps

转载 作者:搜寻专家 更新时间:2023-10-31 19:58:48 25 4
gpt4 key购买 nike

使用 java.nio 必须通过 SelectableChannel 注册对操作的兴趣:

SelectionKey = SelectableChannel.register(selector, interestInOpsBitmask)

注册兴趣:

  • 通过使用新的 Ops 执行 SelectableChannel.register 来覆盖现有的 SelectionKey
  • 对比。用 key.interestOps(key.interestOps() | newOp) 更新现有的 SelectionKey

注销兴趣:

  • SelectionKey.cancel 和 SelectableChannel.register 新操作
  • 对比。像上面那样更新现有的 SelectionKey

有什么优点和缺点吗?

谢谢

最佳答案

如果您总是在 select() 返回后将执行分派(dispatch)到线程池,您可能希望立即取消键,因为您失去了对 Runnable 执行时间的控制。

Ex.: 如果在取消上一个键之前执行下一个select()(线程还在等待执行),它仍然有效,导致另一个线程携带已经派发的键。如果其中一个线程取消了 key ,另一个线程将得到 CancelledKeyException。除了引入意想不到的行为。

即使您取消 key ,线程也可能会在 channel 取消注册(由于您之前的 key.cancel())之前注册相同的 channel (更新选择 key )。又是什么,将导致 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.
}

第一次执行几乎永远不会返回键,但是循环结束时的 select() 可以保证已取消键的 channel 从选择器中注销(由您决定) .

但是,如果您只是在监听选择器事件的同一个线程中执行任务,那么更新听起来既简单又安全。

关于java - NIO 最佳实践——SelectableChannel 和 InterestOps,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2880443/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com