gpt4 book ai didi

SocketChannel.write() 的 Java NIO 线程问题

转载 作者:塔克拉玛干 更新时间:2023-11-02 19:42:44 25 4
gpt4 key购买 nike

有时,在通过 SocketChannel.write() 发送大量数据时,底层 TCP 缓冲区被填满,我必须不断地重试 write() 直到数据全部发送完。

所以,我可能有这样的东西:

public void send(ByteBuffer bb, SocketChannel sc){
sc.write(bb);
while (bb.remaining()>0){
Thread.sleep(10);
sc.write(bb);
}
}

问题是大 ByteBuffer 和溢出的底层 TCP 缓冲区偶尔会出现问题,这意味着对 send() 的调用将阻塞一段意想不到的时间。在我的项目中,有数百个客户端同时连接,一个套接字连接引起的一次延迟可以使整个系统爬行,直到解决一个 SocketChannel 的延迟。发生延迟时,可能会导致项目其他领域的链式 react 变慢,低延迟很重要。

我需要一个解决方案来透明地处理这个 TCP 缓冲区溢出问题,并且在需要多次调用 SocketChannel.write() 时不会导致所有内容阻塞。我考虑过将 send() 放入一个扩展 Thread 的单独类中,以便它作为自己的线程运行并且不会阻止调用代码。但是,我担心为我维护的每个套接字连接创建线程所需的开销,尤其是在 99% 的情况下,SocketChannel.write() 在第一次尝试时成功,这意味着线程不需要存在. (换句话说,只有在使用 while() 循环时才真正需要将 send() 放在单独的线程中——仅在存在缓冲区问题的情况下,可能只有 1% 的时间)如果存在缓冲区问题只有 1% 的时间,我不需要线程的开销来处理其他 99% 的 send() 调用。

我希望这是有道理的...我真的可以使用一些建议。谢谢!

最佳答案

在 Java NIO 之前,您不得不为每个套接字使用一个线程以获得良好的性能。这是所有基于套接字的应用程序的问题,而不仅仅是 Java。为所有操作系统添加了对非阻塞 IO 的支持以克服这个问题。 Java NIO 实现基于Selectors

参见 The definitive Java NIO book还有这个On Java文章开始。但是请注意,这是一个复杂的主题,它仍然会给您的代码带来一些多线程问题。谷歌“非阻塞 NIO”了解更多信息。

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

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