gpt4 book ai didi

java - 如何检测 Selector.wakeup 调用

转载 作者:搜寻专家 更新时间:2023-10-31 20:31:27 24 4
gpt4 key购买 nike

如果我会写:

int selectedChannels = selector.select();Set selectedKeys = selector.selectedKeys();if ( selectedChannels != selectedKeys.size() ) {    // Selector.select() returned because of a call to Selector.wakeup()    // so do synchronization.}// Continue with handling selected channels.

它能正确检测到唤醒调用吗?

背景信息:

我正在编写一个服务器,它大部分时间只接收数据包并将它们存储在一个文件中。应用程序很少需要给自己发送一个特殊的数据包。为此,它启动到服务器套接字的连接(从不同的线程):

SocketChannel channel = SocketChannel.open();channel.configureBlocking( false );channel.connect( new InetSocketAddress( InetAddress.getLocalHost(), PORT ));selector.wakeup();SelectionKey key = channel.register( selector, SelectionKey.OP_CONNECT );

问题是如果主线程已经在 Selector.select() 中,SelectableChannel.register() 可能会阻塞。为了防止这种情况发生,我调用了 Selector.wakeup(),它让主线程从 select() 过早返回。为确保其他线程有机会完成注册调用,我必须同步主线程,但我必须在 every 从 select() 返回后执行此操作。如果我能检测到它是否因为 wakeup() 调用而从 select() 返回,那么我就可以针对这种情况优化它。

因此,理论上顶部代码片段应该可以工作,但我想知道它是否只会这样做,因为它依赖于一些未指定的行为?

感谢任何提示。

最佳答案

根据 Selector#select()Selector#selectedKeys() 的约定,我猜想提议的代码段原则上根本行不通。来自 Selector :

  • The selected-key set is the set of keys such that each key's channel was detected to be ready for at least one of the operations identified in the key's interest set during a prior selection operation. This set is returned by the selectedKeys method.
public abstract int select(long timeout)                throws IOException    Returns:        The number of keys, possibly zero, whose ready-operation sets were        updated

As I read that, the size of the selectedKeys set should always equal the number returned by select by definition. I have noticed - as you may have as well - that some implementations don't quite follow the documentation, and in fact selectedKeys returns all keys with updated ready-operation sets, even if they were not updated during a call to select. The only other indicator that the select woke up due to a call to wakeup might be that the number of keys is zero; however either method would be unreliable, at best.

The usual way to handle this is, as implied, through concurrency control. I wouldn't worry about execution time here; this is a classic example of premature optimization.

Unless you're really worried about single digit microsecond tolerances, you won't notice any slowdown - and if you are worried about that level of tolerance, a Selector isn't going to be reliable enough for you anyway.

Here's an example of the usual mechanism for this, using a ReentrantLock to accomplish the appropriate concurrency:

ReentrantLock selectorGuard;
Selector selector;

private void doSelect() {
// Don't enter a select if another thread is in a critical block
selectorGuard.lock();
selectorGuard.unlock();

selector.select();
Iterator<SelectionKey> keyIter = selector.selectedKeys().iterator();

while(keyIter.hasNext()) {

SelectionKey key = keyIter.next();
keyIter.remove();

// Process key
}
}

private void addToSelector() {

// Lock the selector guard to prevent another select until complete
selectorGuard.lock();

try {
selector.wakeup();

// Do logic that registers channel with selector appropriately

} finally {
selectorGuard.unlock();
}
}

关于java - 如何检测 Selector.wakeup 调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/333593/

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