Java Selector NIO读取问题

时间:2009-09-25 13:32:59

标签: java selector nio

相关守则 - 注意说明只是一个有几种方法的类,它们将对数据进行操作。创建一个新线程对读取的数据进行操作。

READ THREAD:

while(true) {
     System.out.println(".");
     if(selector.select(500) == 0)
          continue;

     System.out.println("processing read");

     for(SelectionKey sk : selector.keys()) {
          Instructions ins = myHashTable.get(sk);
          if(ins == null) { 
               myHashTable.put(sk, new Instructions(sk));
               ins = myHashTable.get(sk);
          }
          ins.readChannel();
     }
}

READCHANNEL

public void readChannel() {
     BufferedReader reader = new BufferedReader(Channels.newReader((ReadableByteChannel) this.myKey.channel(), "UTF-8"));
     Worker w = new Worker(this, reader.readLine());
     (new Thread(w)).start();
}

新线程然后调用更多Instructions方法。

当ins函数完成时,可能写入Writer:

Writer out = Channels.newWriter((WritableByteChannel) key.channel(), "UTF-8");
out.write(output);
out.flush();

我可以确认我的客户端(flash电影),然后接收并对输出进行操作。

最后,w退出。

在收到来自客户端的第一条消息并成功处理之后,READ THREAD循环不再处理任何消息。我相信密钥已在选择器中注册并准备好阅读。我已经通过循环检查所有键来检查它们是否可读取isReadable& isRegistered在频道上,结果在所有情况下都是如此。但是,当从客户端发送第二条消息时,我在读取线程中看到的唯一响应是“。”字符不是每半秒打印出来,而是持续更快。那么,我相信数据存在于通道中,但由于某种原因,Selector没有选择任何键。

任何人都可以帮助我吗?

3 个答案:

答案 0 :(得分:3)

我认为你在这里缺少一点。

  • 首先,你应该在for循环中使用selector.selectedKeys() 如Vijay所述。
  • 应该从selectedKeys中删除密钥 处理密钥后。否则,密钥将不会 自动删除,因此选择器可能连续旋转 如果有一个感兴趣的ops位设置的键。 (这可能是 在你的情况下的问题)。
  • 最后,我们应该对其进行操作 通道如果通道准备就绪。即,只读 isReadable()返回true并尝试仅在isWritable()时写入 真正。别忘了验证密钥。

答案 1 :(得分:2)

不应该

for(SelectionKey sk : selector.keys()) 

for(SelectionKey sk : selector.selectedKeys())

既然您只想处理当前选择操作中发生的那些事件?

由于你说select(500)在5秒之前返回,我的猜测是你已经注册了一个带有WRITE操作选择器的通道。大多数时候,通道都可以写入。因此,只有在数据可用于写入时才有必要将兴趣操作设置为WRITE。

答案 2 :(得分:0)

请注意,您必须从所选键列表中删除该频道。 Select()不会为你做那件事。最好为此目的使用迭代器:

Iterator<SelectionKey> key_interator = selector.selectedKeys().iterator();
while (key_interator.hasNext()) {
  ...
  key_interator.remove();
}