我有一个最小的 JMS 提供程序,它通过 UDP 发送主题消息并通过 TCP 将消息排队。我使用单个选择器来处理 UDP 和 TCP 选择键(同时注册 SocketChannels 和 DatagramChannels)。
我的问题是:如果我只发送和接收 UDP 数据包,一切都很顺利,但是一旦我开始在 TCP 套接字上写入(使用 Selector.wakeup() 让选择器进行实际写入),选择器就会进入无限循环,返回一个空的选择键集,并占用 100% 的 CPU。
主循环的代码(有些简化)是:
public void run() {
while (!isInterrupted()) {
try {
selector.select();
} catch (final IOException ex) {
break;
}
final Iterator<SelectionKey> selKeys = selector.selectedKeys().iterator();
while (selKeys.hasNext()) {
final SelectionKey key = selKeys.next();
selKeys.remove();
if (key.isValid()) {
if (key.isReadable()) {
this.read(key);
}
if (key.isConnectable()) {
this.connect(key);
}
if (key.isAcceptable()) {
this.accept(key);
}
if (key.isWritable()) {
this.write(key);
key.cancel();
}
}
}
synchronized(waitingToWrite) {
for (final SelectableChannel channel: waitingToWrite) {
try {
channel.register(selector, SelectionKey.OP_WRITE);
} catch (ClosedChannelException ex) {
// TODO: reopen
}
}
waitingToWrite.clear();
}
}
}
对于 UDP 发送(TCP 发送类似):
public void udpSend(final String xmlString) throws IOException {
synchronized(outbox) {
outbox.add(xmlString);
}
synchronized(waitingToWrite) {
waitingToWrite.add(dataOutChannel);
}
selector.wakeup();
}
那么,这里有什么问题?我应该使用 2 个不同的选择器来处理 UDP 和 TCP 数据包吗?