为什么每次调用readObject时Java的对象流都返回相同的对象?

时间:2011-11-11 04:11:14

标签: java sockets serialization

原谅伪代码 - 我的无线网络已关闭,我现在无法将代码从我的离线计算机复制到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...

因此看起来正在读取消息对象但未从流中删除。

如何按预期方式疏通我的流并让它们同步?

1 个答案:

答案 0 :(得分:20)

此问题的经典原因是多次发送相同的对象引用。对象流提示保留对象引用标识,并且在接收端,您将在每个readObject()调用上获得相同的对象(即使您已在发送方修改了对象!)。您的伪代码是正确的,但问题是它是否准确反映了您的实际代码。

如果您的问题 是参考问题,您可以通过每次发送不同的对象实例,或者在每个之间使用writeUnshared()和/或调用reset()来解决问题writeObject()致电。使用writeUnshared()将强制主对象成为接收端的新对象实例,但此对象可能引用的其他对象仍可能是共享引用。另一方面,调用reset()将刷新接收端的所有缓存对象,因此接收端的所有对象引用都将是新引用。哪一种更适合通过线路管理数据取决于您的使用情况,但是,对于长时间运行的流,定期调用reset()始终是好的,因为这将释放随着时间的推移而积累的内存(这是使用对象流时常见但微妙的“内存泄漏”)。