繁体   English   中英

检查ObjectInputStream是否有任何要读取的内容而不阻塞?

[英]Check if ObjectInputStream has anything to read without blocking?

我正在用Java构建一个可同时与多个客户端通信的服务器,我们最初的方法是服务器侦听来自客户端的连接,一旦接收到连接并创建了套接字,就产生一个新线程来处理与每个客户端的通信,即使用ObjectInputStream读取请求,执行所需的操作(从DB中获取数据,对其进行更新等),然后将响应发送回客户端(如果需要)。 当服务器本身返回以侦听更多连接时。

暂时可以正常工作,但是这种方法不是真正可扩展的,它对于同时连接少量客户端非常有效,但是由于每个客户端都产生了另一个线程,所以当连接太多客户端时会发生什么立刻?

因此,我的下一个想法是维护一个排序列表,该列表将保存所有已连接的客户端(套接字对象和一些其他信息),使用ThreadPool对其进行遍历并读取它们发送的任何内容(如果收到了消息,则将其放入)一个队列,由另一个工作线程的ThreadPool执行,如果工作程序完成了任务(如果需要响应),则将其发送。

后两个步骤的实现非常简单,问题在于每个客户端实现都使用原始线程,因此我使用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()没有什么不同。

谁能建议一种切实可行的方法?

这是一个很好的问题,您已经完成了一些作业...。但是,这涉及到回顾一些历史以使事情变得正确。 注意,实际上,您的问题更多是与套接字级别的通信有关,而不是与ObjectInputStream有关:

过去最简单的方法是每个套接字有一个单独的线程。 这可以扩展到一定程度,但是线程昂贵且创建缓慢。

作为响应,对于大型系统,人们创建了线程池,并在需要工作时为线程上的套接字提供服务。 这很复杂。

然后,使用java.nio包更改了Java语言,该包将Selector和非阻塞IO一起引入了Selector 这创建了一种可靠的(尽管有时会令人困惑)服务于更少线程的多个套接字的方法。 在您的情况下,这并不能完全/很多地帮助您,因为您想知道何时可以读取完整的对象,而不是何时只有“某些”对象。

在此期间,“环境”发生了变化,Java现在能够更有效地创建和管理线程。 “当前”的想法是,更好/更快,更容易地为每个套接字分配一个线程。...请参阅每个连接模型的Java线程与NIO

就您的情况而言,我建议您坚持使用“每插槽线程数”模型,这样就可以了。 Java可以扩展和处理比套接字更多的线程,因此您会很好的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM