Вопрос по java – Использование ReferenceQueue и WeakReference

10

Я хочу правильно закрыть объект Closeable, когда на него больше не ссылаются другие потоки.

Я написал небольшой тест, но после того, как объект был поставлен в очередь, метод get возвращает значение null, то есть метод poll возвращает соответствующий объект, у которого нет референта.

  public static void main(String[] args)
  {
   ReferenceQueue<Closeable> reaped = new ReferenceQueue<Closeable>();
   Closeable s = <SOME CLOSEABLE IMPL>;
   WeakReference<Closeable> ws = new WeakReference<Closeable>(s, reaped);
   s = null;

   System.gc();
   Closeable ro = (Closeable)reaped.poll().get();
   ro.close();
  }

Заранее спасибо. Любая помощь будет оценена.

Ваш Ответ

1   ответ
7

Во-первых, если речь идет только о закрытии, используйтеPhantomReference. Next, from the reference queue, poll() не гарантирует, что вы получите ссылку обратно. и вы никогда не получите реальный объект (референт) обратно.

Если вы хотите убедиться, что вашCloseableы закрыты, вы должны отслеживать их сами, скажем, вMap<Reference<?>, Closeable>, Тогда когда тыpoll() ваша справочная очередь, вы в конечном итоге получитеref тогда вы должны использовать его, чтобы получитьCloseable с карты.

   class MyThing {
      Closeable c;
   }

   Map<Reference<MyThing>, Closeable> m = new HashMap();
   ReferenceQueue<MyThing> reaped = new ReferenceQueue<MyThing>();

   MyThing mt = new MyThing();
   mt.c = new MyClosable();

   Reference<MyThing> pref = new PhantomReference<MyThing>(mt, reaped);
   m.put(pref, mt.c);

   mt = null;


   System.gc();
   Reference<MyThing> rf = reaped.poll();
   while (rf != null) {
     m.get(rf).close(); 
     rf = reaped.poll();
   }

Note Если у вас нет реальной причины для этого или если вы не понимаете, что вы на самом деле делаете, НЕ делайте такого рода вещи.

Вы можете закрыть свои файлы вfinally и кстати, если речь идет о файлах, сокетах и т. д., они закрыты для вас (они уже реализуютfinalize()

Спасибо, вы правы, поэтому я использовал только интерфейс Closeable, чтобы разрешить только закрытые ресурсы. И я не возражаю, что люди не будут собираться до тех пор, пока не закончится память. yan
Привет, спасибо за такой быстрый ответ, это про IndexSearcher of Lucene. yan
@ Янь, нет гарантии, что ваши объекты получат GCes послеSystem.gc() даже когда вы выходите из JVM. Вы не используете финализацию для своей бизнес-логики. Он существует только для специальных целей, таких как кэширование и (в конечном итоге) предотвращение утечек ресурсов. Вы не можете сказать,commit() или жеrollback() БД транзакций в финализаторе
Я только что попробовал, после System.gc (); размер ReferenceQueue равен нулю. yan
IndexSearcher очень тяжелый объект, и я не вижу, как такой подход может быть нормальным.IndexSearcher обычно хранится как синглтон в течение всего времени применения. Современные версии Lucene должны использоватьSearcherManager или жеNRTManager получить полный цикл обслуживания из коробки.

Похожие вопросы