我正在开发一个一对多的服务器客户端应用程序,这是一个小项目。
由于socket IO是阻塞的。我正在寻找解决方案。
有人能告诉我每个解决方案的优缺点吗?
- 使用java.nio
- 为每个连接的客户端新建一个单独的线程。
谢谢
我正在开发一个一对多的服务器客户端应用程序,这是一个小项目。
由于socket IO是阻塞的。我正在寻找解决方案。
有人能告诉我每个解决方案的优缺点吗?
谢谢
在接收端也是相同的方式进行处理。这很舒适,因为您只需要处理程序逻辑中的顶层(其余大多是每个构造函数调用一次)。
(在我的项目中,我为每个连接都有一个MessageParser-Thread,然后将单独的工作分配给一个ThreadPool,这些工作可能会写入一个或多个打开的连接,而不仅仅是产生它们的那个连接。当然,写入是同步的。)
对于短暂的连接,您实际上不希望每个连接都有一个新线程,而只需在ThreadPool上执行一个新的Runnable,因为构造新线程需要一点时间。(注意:使用JDK 19,我们可以获得廉价的虚拟线程。请使用这些线程,线程池由平台在后台隐藏。)
尽管如此,管理开销仍然相当麻烦,因为您必须跟踪数据所在的位置。(实际上,每个连接都有两个管道,还有一两个线程管理所有管道中的数据,等待选择器上的新数据(或在传出情况下等待新空间)。 (消息解析后的实际处理仍然在ThreadPool中产生的Runnables中进行。)
NIO非常适合高性能应用,建议不要超过#cores个线程,乘以您的应用程序的IO因子。其中,IO因子是您的应用程序等待磁盘IO完成的百分比。
原因很简单,当您有#cores个worker时,每个worker可能会绑定到一个单独的CPU核心,并将其最大化利用。 而且,工作人员越多,则上下文切换就会越多,这正是您使用NIO的原因所在。
如果工人们需要等待IO,则可以处理其他请求,因此请使用比核心更多的工人以实现完全的CPU利用率。
如果您使用线程,您将获得以下优势:
java.nio
并不一定更高效。线程是廉价的,而且您没有考虑SMT。 - Johan Sjöberg