正如主题所示,我有一个服务器和一些客户端。
服务器同时接受 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/