java – Selector.select()启动一个无限循环

我有一个最小的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数据包吗?

解决方法:

我建议你检查select()方法的返回值.

try {
 if(selector.select() == 0) continue;
} catch (final IOException ex) {
 break;
}

您是否尝试调试以查看循环的位置?

编辑:

>我建议不要在迭代器上调用“remove()”,而是在迭代它们之后调用selectedKeys.clear().迭代器的实现可能不会从底层集中删除它.
>检查您是否在连接的通道上注册OP_CONNECT.

上一篇:linux各个版本mysql的卸载


下一篇:写入通道后,Java Selector返回带有OP_READ的SelectionKey,而无需在无限循环中的数据