Java:使用队列管理比线程更多的连接

标签 java multithreading sockets

作为练习,我们将实现一个服务器,该服务器具有一个监听连接、接受连接并将套接字放入 BlockingQueue 的线程。然后,池中的一组工作线程遍历队列并处理通过套接字传入的请求。

每个客户端连接到服务器,发送大量请求(在发送下一个请求之前等待响应)并最终在完成后断开连接。

我当前的方法是让每个工作线程在队列上等待,获取套接字,然后处理一个请求,最后将(仍然打开的)套接字放回到队列中,然后再处理另一个可能来自不同客户端的请求。客户端的数量比工作线程的数量多得多,因此有很多连接排队。

这种方法的问题是:即使客户端没有发送任何内容,线程也会被客户端阻塞。可能的伪解决方案,均不令人满意:

  • inputStream上调用available(),如果返回0,则将连接放回队列。问题:无法检测客户端是否仍然连接.
  • 如上所述,但使用 socket.isClosed()socket.isConnected() 来确定客户端是否仍处于连接状态。问题:这两种方法都没有检测到客户端挂起,正如 EJP 在 Java socket API: How to tell if a connection has been closed? 中很好地描述的那样。
  • 通过读取或写入客户端来探测客户端是否仍然存在。问题:读取 block (即回到不活动客户端阻塞队列的原始情况)和写入实际上向客户端发送一些内容,导致测试失败。

有办法解决这个问题吗? IE。是否可以在不阻止或发送某些内容的情况下区分断开连接的客户端和被动客户端?

最佳答案

简短回答:不。如需更长的答案,请参阅 EJP 的答案。

这就是为什么您可能根本不应该将套接字放回队列,而是处理来自套接字的所有请求,然后将其关闭。将连接传递给不同的工作线程来分别处理请求不会给您带来任何优势。

如果您的客户端表现不佳,您可以在套接字上使用读取超时,因此读取只会阻塞,直到超时发生。然后您可以关闭该套接字,因为您的服务器没有时间迎合表现不佳的客户端。

关于Java:使用队列管理比线程更多的连接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46666269/

相关文章:

java - 为 Java GUI 选择布局管理器和面板数量

vb.net - 如何让一个线程等到另一个线程完成?

multithreading - 在 Julia 中并行粒子群优化

c++ - 如何中断epoll_pwait来捕捉信号

C++ 套接字接受 block cout

java - 类不是抽象的,不会重写 KeyListener 中的抽象方法 keyReleased(KeyEvent)

java - 如何使用 ReplaceAll() 方法将整个字符串替换为空值?

java - 同时读取数组线程安全吗?

.net - Socket 异步发送和接收数据

sockets - 在 dart 中将 SocketServer 作为 Isolate 运行