我正在用java构建一个同时与多个客户端通信的服务器,我们最初的方法是服务器监听来自客户端的连接,一旦接收到连接并创建了一个套接字,就会产生一个新线程处理与每个客户端的通信,即使用 ObjectInputStream 读取请求,执行所需的操作(从数据库中获取数据、更新数据等),并将响应发送回客户端(如果需要)。而服务器本身又回去收听更多的连接。
这暂时可以正常工作,但是这种方法并不是真正可扩展的,它适用于同时连接的少量客户端,但是由于每个客户端都会产生另一个线程,当连接的客户端过多时会发生什么立刻?
所以我的下一个想法是维护一个包含所有连接客户端(套接字对象和一些额外信息)的排序列表,使用 ThreadPool 遍历它们并读取它们发送的任何内容,如果收到消息然后将其放入由另一个工作线程的 ThreadPool 执行的队列,一旦工作人员完成其任务,如果需要响应,则发送它。
后面的 2 个步骤实现起来非常简单,问题是每个客户端实现的原始线程,我使用 ObjectInputStream.readObject() 来读取消息,并且这个方法阻塞直到有东西要读取,这很好方法,但我不能对新方法使用相同的东西,因为如果我阻塞每个套接字,我将永远无法到达列表中更靠后的那些。
所以我需要一种方法来检查在调用 readObject() 之前是否有任何要阅读的内容,到目前为止,我尝试了以下解决方案:
解决方案 1: 使用 ObjectInputStream.available() 检查是否有可读取的内容,此方法失败,因为此方法似乎总是返回 0,无论流中是否存在对象。所以这根本没有帮助。
解决方案2: 使用PushbackInputStream检查流中第一个未读字节是否存在,如果存在则将其推回并使用ObjectInputStream读取对象,如果不继续:
boolean available;
int b = pushbackinput.read();
if (b==-1)
available = false;
else
{
pushbackinput.unread(b);
available = true;
}
if (available)
{
Object message= objectinput.readObject();
// continue with what you need to do with that object
}
这也被证明是无用的,因为如果没有要读取的输入, read() 也会阻塞。如果流已关闭,它似乎只返回 -1 选项。如果流仍然打开但为空,它只是阻塞,所以这与简单地使用 ObjectInputStream.readObject(); 没有什么不同;
任何人都可以提出一种实际可行的方法吗?