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

2022-09-04 08:05:31

原谅伪代码 - 我的无线网络已关闭,我目前无法将代码从我的离线计算机复制到StackExchange上。

我有两个java应用程序,通过 java.net.*套接字连接。我正在尝试通过对象输入/输出流将“消息”对象从一个对象传递到另一个对象。

以下是我正在做的事情:

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;
     }
}

服务器

服务器有一个名为“发件箱”的队列

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

此问题的典型原因是多次发送相同的对象引用。对象流 impls 保留对象引用标识,在接收端,您将在每次 readObject() 调用时返回相同的对象(即使您在发送端修改了对象!)。您的伪代码是正确的,但问题是它是否准确地反映了您的实际代码。

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


答案 2