原谅伪代码 - 我的无线网络已关闭,我现在无法将代码从我的离线计算机复制到StackExchange上。
我有两个java应用程序,通过java.net。* socket连接。我试图通过对象输入/输出流将“消息”对象从一个传递到另一个。
这就是我正在做的事情:
Class Message implements Serializable
{
String text
int data
public Message(String txt, int dat)
{
this.text = txt;
this.data = dat;
}
string toString()
{
return text + " " + data;
}
}
服务器:
服务器有一个名为Outbox的队列
for(int i = 0; i < 1000; i++)
{
Message adding = new Message("Hello!",i);
Outbox.add(temp)
Message temp = Outbox.poll();
out.writeObject(temp);
system.out.println(temp)
}
客户端:
for(int i = 0; i < 1000; i++)
{
Message temp;
temp = in.readObject()
system.out.println(temp)
}
现在我希望很明显我希望每个程序的控制台看起来都一样。相反,这就是我正在考虑的问题。
服务器
Hello 0
Hello 1
Hello 2
Hello 3...
客户端
Hello 0
Hello 0
Hello 0
Hello 0...
因此看起来正在读取消息对象但未从流中删除。
如何按预期方式疏通我的流并让它们同步?
答案 0 :(得分:20)
此问题的经典原因是多次发送相同的对象引用。对象流提示保留对象引用标识,并且在接收端,您将在每个readObject()调用上获得相同的对象(即使您已在发送方修改了对象!)。您的伪代码是正确的,但问题是它是否准确反映了您的实际代码。
如果您的问题 是参考问题,您可以通过每次发送不同的对象实例,或者在每个之间使用writeUnshared()
和/或调用reset()
来解决问题writeObject()
致电。使用writeUnshared()
将强制主对象成为接收端的新对象实例,但此对象可能引用的其他对象仍可能是共享引用。另一方面,调用reset()
将刷新接收端的所有缓存对象,因此接收端的所有对象引用都将是新引用。哪一种更适合通过线路管理数据取决于您的使用情况,但是,对于长时间运行的流,定期调用reset()
始终是好的,因为这将释放随着时间的推移而积累的内存(这是使用对象流时常见但微妙的“内存泄漏”)。