Почему Java Stream объекта возвращает один и тот же объект каждый раз, когда я вызываю readObject? - PullRequest
11 голосов
/ 11 ноября 2011

Простите за псевдокод - у меня отключены беспроводные сети, и я не могу скопировать код со своего автономного компьютера на 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 Ответ

20 голосов
/ 11 ноября 2011

классическая причина этой проблемы - отправка одной и той же ссылки на объект несколько раз. Поток объектов подразумевает сохранение идентификатора ссылки на объект, и на принимающей стороне вы будете возвращать один и тот же объект при каждом вызове readObject () (, даже если вы изменили объект на отправляющей стороне! ). Ваш псевдокод правильный, однако вопрос в том, точно ли он отражает ваш фактический код.

если ваша проблема является ссылочной проблемой, вы можете решить эту проблему, отправляя каждый раз разные экземпляры объекта, или используя writeUnshared() и / или вызывая reset() между каждым вызовом writeObject(). использование writeUnshared() заставит главный объект быть новым экземпляром объекта на принимающей стороне, но другие объекты, на которые может ссылаться этот объект, могут все еще быть общими ссылками. с другой стороны, вызов reset() сбросит все кэшированные объекты на принимающей стороне, поэтому все ссылки на объекты на принимающей стороне будут новыми ссылками. какой из них лучше использовать для управления данными по проводам, зависит от вашего варианта использования, однако для длинных потоков всегда полезно периодически вызывать reset(), так как это освободит память, которая будет со временем накапливаться (это является распространенной, но незначительной «утечкой памяти» при использовании потоков объектов).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...