java - NIO 选择器 : How to properly register new channel while selecting

标签 java multithreading nio

我有一个子类化的 Thread,它有一个私有(private)的 Selector 和一个允许其他线程的公共(public) register(SelectableChannel channel, ...) 方法将 channel 注册到选择器。

如回答here , channel 的 register() 在选择器的 select()/select(long timeout) 期间阻塞,所以我们需要 wakeup() 选择器。

我的线程无限期地选择(除非它被中断)并且它实际上设法在 channel 的 register() 被调用之前进入下一个选择。所以我想我使用一个简单的锁和 synchronized block 来确保 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() 在线程继续下一个选择循环之前发生。据我测试,这按预期工作。

问题: 这是一种“好”的方法还是有任何严重的缺点?使用 List 或 Queue(如建议的 here )来存储注册 channel 或更复杂的锁(如 this)会更好吗?反而?这样做的优点/缺点是什么?或者有什么“更好”的方法吗?

最佳答案

只需将选择器等视为非线程安全的,按照 Darron 的建议在同一个线程上执行所有与选择相关的操作。

NIO 选择器的并发模型是bullshit。我必须大声疾呼,因为这对每个试图研究它的人来说都是在浪费时间。最后得出的结论是,算了,不能并发使用。

关于java - NIO 选择器 : How to properly register new channel while selecting,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12822298/

相关文章:

仅当远程 TCP 服务器关闭时,Java NIO 客户端才会导致文件描述符泄漏

java - 主要使用 javascript 和 JMeter 进行负载测试 Tapestry 应用程序

java - lambda 表达式可以替代多态性吗?

c++ - 等待通知 pthreads unix C++

java - Java 定时器的多线程

java - 读写性能filechannel和RandomAccessFile谁更好?

java - NIO 阻塞写入不起作用

java - 我有三个复选框,因为连续三列都被选中,但我想从该行中选择一个。如果选择其中一个则取消选择

java - 在java中的十六进制字符串中应用2的补码

Java 在执行 Activity 中的代码之前等待线程(在另一个类中)完成