java - 客户端线程挂起模拟会阻止服务器在客户端设置等待期间接受任何 I/O

标签 java multithreading concurrency client

正如主题所示,我有一个服务器和一些客户端。
服务器同时接受 I/O 连接(套接字连接中没有排队),但我遇到了这个令人不安的问题,我不知道如何绕过它! 如果我强制客户端抛出 I/O 异常,服务器会检测到它并正确终止客户端线程(从任务管理器 (Windows) 和系统监视器 (Ubuntu) 进行验证)。但是如果我模拟一个“挂起”的 I/O,例如

Thread.sleep(60*1000);

私有(private)静态对象锁 = new Object();

synchronized(lock) {
   while (true) {
      try {
         lock.wait();
      } catch (InterruptedException e) {
         /* Foo */
      }
   }
} 

然后所有后续 I/O 操作(连接和数据传输)似乎都会阻塞或等待,直到“挂起”客户端终止。应用程序利用 ExecutorService,因此如果“挂起”客户端未在建议的时间限制内完成操作,则任务将超时并且客户端将被迫退出。随后“阻塞”的 I/O 将恢复,但我想知道为什么当客户端“挂起”时服务器不接受任何 I/O 连接或执行任何 I/O 操作?

注意:客户端线程发生在服务器主线程中,如下所示:

while (true) { 
   accept client connection;
   submit client task;
          ||
         \  /
          \/ 
   // ExecutorService here in the form 
   // spService.submit(new Callable<Tuple<String[], BigDecimal[]>>() { 
   // ... code ... }}).get(taskTimeout, taskTimeUnit);
   check task result & perform cleanup if result is null;
   otherwise continue;
}

最佳答案

问题:

这很可能表明您的服务器同时接受客户端连接,但是,它仅同步处理这些连接。这意味着即使一百万个客户端在任何给定时间成功连接,如果其中任何一个花费很长时间(或挂起),它就会阻碍其他客户端。

测试:

为了验证这一点:我将通过在客户端中添加 Thread.sleep 语句(1000)来切换客户端连接所需的时间。

预期结果:

我相信您会发现,即使在客户端中添加单个 Thread.sleep(1000) 语句也会使所有其他连接客户端延迟 1000。

关于java - 客户端线程挂起模拟会阻止服务器在客户端设置等待期间接受任何 I/O,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8156062/

相关文章:

java - 用于在短语中搜索单词的数据结构

multithreading - ZeroMQ/Python - CPU 亲和性问题?

java - 将类实例作为线程单独运行

go - for循环中的Goroutines返回不同的值

c# - 围绕同时处理单个和批量请求的架构

php - 使用 PHP、Javascript 和 MySQL 的并发

java - 在哪里可以找到 Mac OS 的 jni 头文件

java - Java 10 中的 "restricted keyword"和 "reserved type name"之间的概念区别是什么?

java - IJKplayer 在播放某些视频时崩溃

android - 为什么我们应该使用 aysntask 或 service 而不是新线程