SocketChannel.read()无限期地阻塞

时间:2011-10-06 15:39:56

标签: java nio blocking socketchannel

我很难搞清楚这一个。我有以下代码:

    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()的调用会在没有返回的情况下阻塞。有没有我错过的东西?

2 个答案:

答案 0 :(得分:1)

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

我也想知道为什么你没有记录IOException,以及为什么你只是取消密钥而不是关闭频道。所以我也想知道你不知道的I / O例外情况。

同样分配缓冲区是非常昂贵的:你不应该在每次读取时都这样做,你应该在分配给通道的SocketEventHandler实例中有一个作为会话状态。

答案 1 :(得分:0)

您是否在代码中的某处调用了channel.configureBlocking( false )

很难说这里使用的是哪种频道,但我认为SocketChannel最初是以阻止模式创建的。