Что представляет собой состояние слабой ссылки, которая была вручную выставлена ​​в очередь?

Какое состояние объекта, когда вы вручную устанавливаете ссылку?

this.s = "foo";
WeakReference<String> wr = new WeakReference<String>(this.s);
wr.enqueue();

Вся документация, которую я нашел, рассказывает о сборщике мусора, в который помещается объект, а не о том, что происходит, когда вы делаете это вручную.

И есть ли ситуация, когда это имеет смысл? Что это означает, что объект должен быть помещен в очередь, но все же иметь доступные ссылки (сильный, слабый, phantom)?

Изменить: дополнительный вопрос о дополнительном бонусе: снова ли объект снова ставится в очередь, когда он становится недоступным в отдаленном будущем?

Ответ 1

Сильная ссылка останется, поэтому объект не имеет права на сбор. Как указывает JVestry, если вы создаете слабую ссылку с очередью, то wr.enqueue() возвращает true, как ожидалось.

Потенциальное использование для этого заключалось бы в том, чтобы ваш обработчик мог работать на объекте, подверженном либо его ожидающей сборке мусора, либо другому изменению состояния системы, где вы хотели бы предпринять те же действия, что и при сборке объекта, например возможно, вы сохраняете мягкую ссылку на то, что содержит системные ресурсы, чтобы система могла обрабатывать ситуацию с низкой памятью, в то время как вы все еще можете управлять закрытием ресурсов самостоятельно, если вы закончите нормально.

Во втором вопросе ссылка только один раз выставляется в очередь, независимо от того, выполняете ли вы ее с помощью enqueue() или gc делает это как часть коллекции.

РЕДАКТИРОВАТЬ Важно помнить, что отношение между эталонным знаком относится к ссылке, в данном случае wr, а не референт, в данном случае s. Вы могли бы иметь несколько слабых ссылок на один и тот же объект и достигнуть нескольких экземпляров (вроде), по одному для каждой слабой ссылки. Но это слабая ссылка, которая находится в очереди, а не референт, хотя она должна быть доступна из слабой ссылки. Подробнее см. Javadoc в java.lang.ref в разделе "Уведомления".

Ответ 2

В Java есть хорошая статья о типах ссылок: http://weblogs.java.net/blog/enicholas/archive/2006/05/understanding_w.html

В нескольких словах: Вы можете сделать что-то вроде этого:

public class Main {
    public static void main(String[] args) throws InterruptedException{
        String weakString = "Help me";
        ReferenceQueue<String> refQ = new ReferenceQueue<String>();
        WeakReference<String> weakRef = new WeakReference<String>(weakString, refQ);
        //there is no more "hard reference to the string"
        weakString = null;
        //there is no object in ReferenceQueue
        System.out.println(refQ.poll());
        //put the object in the ReferenceQueue
        weakRef.enqueue();
        while (true) {
            //There will be returned "Help me" until the garbage collector will "kill" 
            //"weak" string. This will be done after some time because there are no                                     
            //more strong references to the string. After that will be returned a null  
            //object.
            System.out.println(weakRef.get());
            //only one time there will be returned a refenrece to the String object
            System.out.println(refQ.poll());
            Thread.sleep(1000);
        }
    }
}

Это предназначено для работы с каким-то кешем. Таким образом, вы можете быть уверены, что долгое время не будет использоваться неиспользуемый объект в памяти. ReferenceQueue можно использовать для выполнения какой-либо очистки после вызова weakRef.enqueue();. Например, закрытие файлов или потоков, которые использовались для работы с данными.

Ответ 3

В вашем случае wr.enqueue() вернет false, потому что вы не указали очередь при создании WeakReference. Если вы создаете ReferenceQueue при создании WeakReference, wr.enqueue() вернет true.

Задание слабых ссылок вручную не имеет смысла. Это похоже на запись, что слабая ссылка была собрана мусором, когда она не имеет: 's' по-прежнему является сильной ссылкой на "foo".

Ответ 4

есть ли ситуация, когда это имеет смысл?

ReferenceQueue иногда используются для управления ресурсами, в таком случае вызывая enqueue() самостоятельно, чтобы освободить ресурсы до запуска GC, имеет смысл, так как некоторые ресурсы довольно ограничены (это можно сделать с помощью метода dispose() с слабое упоминание себя как безопасность).

добавлено: Это может быть полезно, если очистка требует времени, так как справочные данные могут быть прочитаны в их собственном потоке, они не повесят ваш основной поток.

Что означает, что объект должен быть помечен в очередь, но для получения доступных ссылок (сильный, слабый, phantom)?

В документах указывается, что он вызывается после того, как ссылка на объект установлена ​​в значение null, поэтому enqueue() не может напрямую влиять на состояние объекта. В текущей документации указано, что вызов очереди не используется gc, он предназначен для очереди Reference перед тем, как gc сделает это. Указанный объект не будет затронут этим вызовом, однако код очистки, читающий ссылочный реквизит, может распоряжаться ресурсами, используемыми этим объектом.

редактирует: Теперь проверено 1.6 документа, поэтому исправлена ​​ошибка в gc с использованием enqueue (старые документы не указали это, однако имеет смысл ограничить воздействие gc на код пользователя)