7

I am implementing a simple file server using Java NIO with one selecting thread and multiple worker threads(for performing real read/write).

The main part of the code looks like the following:

while (true) {
    int num = selector.select();
    if (num > 0) { 
        Iterator<SelectionKey> keys = selector.selectedKeys().iterator();
        final SelectionKey key = keys.next();
        keys.remove();

        if (key.isValid()) {
            if (key.isAcceptable()) {
                accept(key);
            } else if (key.isReadable()) {
                performReadInWorkerThread (key);
            } else if (key.isWritable()) {
                performWriteInWorkerThread (key);
            }
        }
    }
}

As you can see from the code snippet, when a readable/writable channel is selected, I offload the read/write from the selecting thread to a worker thread.

Now the problem is that when a readble channel is handed over to the worker thread, and before it finishes/starts reading from the channel, the selecting thread loops again, and selector.select() selects the previously selected readable channel(because there's still input buffer in the channel that is not yet fully consumed by the previously assigned worker thread), so again the channel is handed over to another worker thread, resulting in multiple worker threads reading the same channel.

I believe this is a design problem. My question is how I can ensure only one thread reading a channel at the same time?

4

2 回答 2

7

为什么?读取不会阻塞。在当前线程中执行。这样你只会遇到无穷无尽的问题。您必须在移交给读取线程之前取消注册 OP_READ,这很容易,但困难的部分是当读取线程完成读取时,它必须重新注册 OP_READ,这需要 (i) 选择器唤醒(),这会导致选择线程在可能无事可做时运行,这是浪费的,或者(ii)使用挂起的重新注册队列,这会将该通道上的下一次读取延迟到下一次选择器之后唤醒,这也很浪费,否则您必须在添加到队列时立即唤醒选择器,如果没有准备好,这也很浪费。我从未见过使用不同选择和读取线程的令人信服的 NIO 架构。

不要这样做。如果您必须使用多线程,请将您的通道组织成组,每个组都有自己的选择器和自己的线程,并让所有这些线程自己阅读。

同样,无需在单独的线程中编写。当你有东西要写的时候就写。

于 2012-07-03T06:38:56.437 回答
4

对于 NIO,只需记住一个原则: 在主选择线程中进行读/写。 这个原理是硬件性质的体现。不要担心在主选择线程中读取速度不快。在现代服务器中,CPU 总是比网卡快。所以一个线程中的无阻塞读取也比网卡操作要快。一个线程已经足够读取数据包了。我们不需要更多线程。

于 2013-02-05T15:15:06.353 回答