gpt4 book ai didi

具有多线程的 Java NIO SocketChannel.read()

转载 作者:塔克拉玛干 更新时间:2023-11-03 04:18:29 25 4
gpt4 key购买 nike

我正在使用带有一个选择线程和多个工作线程(用于执行真正的读/写)的 Java NIO 实现一个简单的文件服务器。

代码的主要部分如下所示:

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.

现在的问题是,当可读 channel 被移交给工作线程时,在它完成/开始从 channel 读取之前,选择线程再次循环,并且 selector.select()选择之前选择的可读 channel (因为 channel 中还有输入缓冲区还没有被之前分配的工作线程完全消耗),所以再次将 channel 交给另一个工作线程,导致多个工作线程读取同一个 channel

我认为这是一个设计问题。我的问题是如何确保只有一个线程同时读取一个 channel ?

最佳答案

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

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

同样不需要在单独的线程中编写。有事就写。

关于具有多线程的 Java NIO SocketChannel.read(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11305386/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com