在考虑使用阻塞套接字时,我可以使用哪些选项?

时间:2017-03-11 03:06:49

标签: java multithreading sockets networking io

虽然利用Java的阻塞套接字,我打算单独读写,但我发现我的两个选项要么为每个操作专用一个单独的线程,要么使用cause轮询超时。

在两个实现之间做出选择似乎是内存(线程)与CPU时间(轮询)的权衡。

我看到许多线程的调度程序和上下文切换可能出现的扩展问题,这可能超过轮询所花费的CPU时间以及从单个线程读取和写入之间可能发生的延迟,具体取决于收到的数据包的大小。或者,如果适当调整,可以使用一小块线程进行缩放,并结合几个套接字的轮询。

除了Java的NIO作为替代方案,这超出了本问题的范围之外,我是否正确理解了使用阻塞套接字可以使用的选项?

2 个答案:

答案 0 :(得分:1)

首先,我认为你排除了唯一可扩展的选择;即使用NIO。

每个套接字线程或轮询都不会扩展。

  • 在线程情况下,每个插槽需要两个线程。 (线程池不起作用。)这会占用线程堆栈和Thread对象的空间,本机线程描述符的内核资源。然后是辅助效果,例如上下文切换,额外的GC跟踪等。

  • 在轮询案例中,您需要为每个套接字定期进行系统调用。无论您是使用一个线程还是一个小线程池执行此操作,系统调用的数量都是相同的。如果您更频繁地轮询,则系统调用率会增加。如果轮询频率较低,则系统响应速度会降低。

AFAIK,鉴于您设置的限制,没有其他选择。

现在,如果你想弄清楚哪个线程和轮询更好,答案就是,"它取决于"。有很多变数:

  • 备用物理内存量和备用CPU周期。
  • 插座数量。
  • 套接字的相对活动。
  • 响应能力的要求。
  • JVM中还有什么(例如触发GC)
  • JVM外面还有什么。
  • 操作系统性能特征。

这些都是一个复杂的场景,数学分析可能太难,难以模拟(准确),难以根据经验进行测量。

答案 1 :(得分:1)

不完全。

首先,使用超时读取并不比没有超时读取更昂贵。在任何一种情况下,如果有数据存在,则告诉操作系统将其唤醒后,线程会进入休眠状态。如果你有超时,它还会告诉操作系统在指定的延迟后唤醒它。没有cpu周期浪费等待。

另一方面,上下文切换开销大约有几千个cpu周期,所以大约几微秒。 <网络通信的延迟> 1毫秒。在此开销使服务器瘫痪之前,您可能会服务数千个并发连接。