NIO选择器:如何在选择时正确注册新通道
我有一个使用私有和公共方法的子类化,该方法允许其他线程将通道注册到选择器。Thread
Selector
register(SelectableChannel channel, ...)
正如这里所回答的,通道在选择器/期间阻塞,所以我们需要选择器。register()
select()
select(long timeout)
wakeup()
我的线程无限期地选择(除非它被中断),它实际上设法在调用通道之前进入下一个选择。所以我想我使用一个简单的锁和块来确保首先发生。register()
synchronized
register()
代码:(为了便于阅读,删除了不相关的代码)
public class SelectorThread extends Thread {
...
public void register(SelectableChannel channel, Attachment attachment) throws IOException {
channel.configureBlocking(false);
synchronized (this) { // LOCKING OCCURS HERE
selector.wakeup();
channel.register(selector,
SelectionKey.OP_READ,
attachment);
}
}
@Override
public void run() {
int ready;
Set<SelectionKey> readyKeys;
while (!isInterrupted()) {
synchronized (this) {} // LOCKING OCCURS HERE
try {
ready = selector.select(5000);
} catch (IOException e) {
e.printStackTrace();
continue;
}
if (ready == 0) {
continue;
}
readyKeys = selector.selectedKeys();
for (SelectionKey key : readyKeys) {
readyKeys.remove(key);
if (!key.isValid()) {
continue;
}
if (key.isReadable()) {
...
}
}
}
}
}
这个简单的锁定允许在线程继续下一个选择循环之前发生。据我测试,这符合预期。register()
问题:这是一种“好”的方式,还是有什么严重的缺点?使用列表或队列(如此处建议)来存储用于注册的通道,还是使用像这样的更复杂的锁更好?这有什么优点/缺点?或者有什么“更好”的方法吗?