Подтвердить что ты не робот

Когда следует использовать слабые ссылки?

Недавно я наткнулся на кусок кода Java с помощью WeakReferences - я никогда не видел их развернутыми, хотя я встретил их, когда они были введены. Это что-то, что должно регулярно использоваться или только когда у вас проблемы с памятью? Если последнее, можно ли их легко модифицировать или требуется код для серьезного рефакторинга? Может ли средний программист Java (или С#) игнорировать их?

РЕДАКТИРОВАТЬ Может ли любой ущерб быть вызван чрезмерным использованием WR?

4b9b3361

Ответ 1

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

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

Пример. Если у меня есть куча объектов Foo в моем приложении, я, возможно, захочу использовать Set, чтобы сохранить центральную запись всех Foo, которые у меня есть. Но, когда другие части моего приложения удаляют объект Foo, удаляя все ссылки на него, я не хочу, чтобы оставшаяся ссылка My Set удерживала этот объект, чтобы он не был собран мусором! На самом деле я просто хочу, чтобы он исчез из моего набора. Здесь вы можете использовать что-то вроде слабого набора (Java имеет WeakHashMap), который использует слабые ссылки на его элементы вместо "сильных" ссылок.

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

Ответ 2

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

Небольшой пример: событие таймера, которое обновляет некоторые данные. Любое количество объектов может подписаться на таймер, чтобы получить уведомление, но тот факт, что они подписались на таймер, не должен сохранять их в живых. Поэтому таймер должен иметь слабые ссылки на объекты.

Ответ 3

Может ли любой ущерб быть нанесен чрезмерное использование WR?

Да, это возможно.

Одна из проблем заключается в том, что слабые ссылки делают ваш код более сложным и потенциально подверженным ошибкам. Любой код, который использует слабую ссылку, должен иметь дело с тем, что ссылка была нарушена каждый раз, когда она ее использует. Если вы пересиливаете слабые ссылки, вы в конечном итоге написали много дополнительного кода. (Вы можете смягчить это, сокрыв каждую слабую ссылку за методом, который выполняет проверку, и повторно создает отброшенный объект по требованию. Но это может быть не так просто, как это: например, если процесс повторного создания включает в себя сеть доступа, вам необходимо справиться с возможностью сбоя повторного создания.)

Вторая проблема заключается в том, что накладные расходы во время выполнения с использованием слабых ссылок. Очевидные затраты - это создание слабых ссылок и вызов get для них. Менее очевидная стоимость заключается в том, что при выполнении GC выполняется значительная дополнительная работа.

Конечная проблема заключается в том, что если вы используете слабые ссылки для чего-то, что ваше приложение, скорее всего, понадобится в будущем, вы можете нести расходы на повторное воссоздание. Если эта стоимость высока (с точки зрения времени процессора, пропускной способности ввода-вывода, сетевого трафика и т.д.), Ваше приложение может плохо работать в результате. Возможно, вам лучше дать JVM больше памяти и вообще не использовать слабые ссылки.

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

Ответ 4

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