1

我很难弄清楚这一点。我有以下代码:

    if (selector.select(1000) <= 0) {
        return;
    }
    Set<SelectionKey> selectionKeys = selector.selectedKeys();
    for (SelectionKey key : selectionKeys) {
        try { 
            SocketEventHandler handler = (SocketEventHandler) key.attachment();
            if (key.isValid() && key.isAcceptable()) {
                handler.becomesAcceptable(key);
            }
            if (key.isValid() && key.isReadable()) {
                handler.becomesReadable(key);
            }

            if (key.isValid() && key.isWritable()) {
                handler.becomesWritable(key);
            }

            if (key.isValid() && key.isConnectable()) {
                handler.becomesConnectable(key);
            }
        } catch (IOException e) {
            key.cancel();
        }
    }
    selector.selectedKeys().clear();

使用以下处理程序代码进行读取:

synchronized public void becomesReadable(SelectionKey key) throws IOException {
    ByteBuffer temporaryBuffer = ByteBuffer.allocate(DEFAULT_BYTE_BUFFER_SIZE);
    temporaryBuffer.position(0);
    int read = -1;
    try {
        read = channel.read(temporaryBuffer);
    } catch (IOException e) {
        prefixLogger.debug("Trace:", e);
        close();
    }
    ...
}

这是唯一调用处理函数的地方。因此,如果我进入该becomeReadable()函数,则通道处于可读状态,但对read()块的调用却没有返回。有什么我错过的吗?

4

2 回答 2

1

我想知道为什么 becomeReadable() 方法是同步的。使用 NIO 时同步越少越好。

我还想知道为什么您不记录 IOException,以及为什么您只是取消密钥而不是关闭通道。所以我也想知道你得到了哪些你不知道的 I/O 异常。

分配缓冲区也非常昂贵:您不应该在每次读取时都这样做,您应该在分配给通道的 SocketEventHandler 实例中将其作为会话状态。

于 2011-10-06T21:14:34.570 回答
0

您是否在代码中的某个地方调用channel.configureBlocking( false )过?

很难说你在这里使用什么样的频道,但我认为SocketChannel最初是在阻塞模式下创建的。

于 2011-10-06T15:56:23.413 回答