我正在使用Java和ObjectInputStream
以及ObjectOutputStream
来编写TCP客户端/服务器对。服务器通过ObjectOutputStream
发送数据,客户端接收ObjectInputStream
中的数据。
部分客户端代码如下:
try {
newMessage = (Message) in.readObject();
System.out.println(newMessage);
} catch (Exception e) { // temporary
System.out.println(e);
}
不幸的是readObject()
是一种阻止方法,这意味着如果ObjectInputStream
中没有新的对象,它只会等到一个到达。
(注意:与readInt()
不同,readObject()
在达到EOF时不会抛出EOFException
。)
这是一个问题:这可能是在一个单独的线程中,但我不希望线程在等待新消息到达时挂起。我宁愿使用Timer
来安排定期检查ObjectInputStream
。
如何检查ObjectInputStream
中是否有新数据,以便在没有新数据时我可以避免调用readObject()
?
答案 0 :(得分:2)
正确的实施是阻止。尝试确定是否有足够的可用数据将无法可靠地工作,因为您甚至不知道需要查找多少字节。 Streams通常也不知道有多少数据可用,因为这取决于操作系统处理网络堆栈和其他参数的某处。
在java.nio
包中阻塞流的非阻塞替代方案可以处理单个线程中的多个连接,但这是一个完全不同的故事。
答案 1 :(得分:0)
写入端可以通过ByteArrayOutputStream将对象写入字节数组。然后它发送长度(int)然后发送字节arrray。接收方读取长度,然后将字节读入字节数组,然后通过ByteArrayInputStream从字节数组中读取对象
答案 2 :(得分:0)
我的建议是使用Netty等NIO框架来解决这个问题。 Netty是基于事件的。当NIO线程(由Netty本身管理)解码传入消息时,您将收到相应的事件。然后,您可以将消息发送到您自己的工作线程并进行处理。
或者,如果您不想涉及第三方依赖项,只需使用两个线程来解决此问题。一个线程在readObject()
上循环并阻塞,一旦获得传入消息,它就会将消息放入队列,例如java.util.concurrent.LinkedBlockingQueue
。另一个线程计划使用LinkedBlockingQueue.peek()
方法以某种速率检查队列。如果peek
返回了某些内容,只需将poll
从队列中取出并处理它。如果没有,线程将不会被阻止,因此它可能会被阻止。