Существует ли java.util.concurrent эквивалент для WeakHashMap?
-
20-09-2019 - |
Вопрос
Можно ли переписать следующий фрагмент кода без использования Collections.synchronizedMap()
все же сохраняя корректность при параллелизме?
Collections.synchronizedMap(new WeakHashMap<Class, Object>());
т. е.есть ли что-нибудь из java.util.concurrent, что можно использовать вместо этого?Обратите внимание, что простая замена на
new ConcurrentHashMap<Class, Object>(new WeakHashMap<Class, Object>()));
очевидно, что это не сработает
Решение
Гуава's Конструктор кэша класс позволяет вам сделать это легко.
CacheBuilder.newBuilder().weakKeys().build()
Обратите внимание, что это изменяет семантику равенства ключей на ==
вместо того , чтобы .equals()
что не будет иметь значения в вашем случае использования Class
экземпляры, но это потенциальная ловушка.
Другие советы
Я не верю, что это так.На самом деле javadoc предлагает использовать коллекции.synchronizedMap()
"Как и большинство классов коллекции, этот класс не синхронизирован.Синхронизированная WeakHashMap может быть создана с использованием Collections.Метод synchronizedMap."
Кофеин является популярным конкурентом Guava cache.
- keys automatically wrapped in weak references
- values automatically wrapped in weak or soft references
использование:
LoadingCache<Key, Graph> graphs = Caffeine.newBuilder()
.weakKeys()
.weakValues()
.build(key -> createExpensiveGraph(key));
Работает ли по-прежнему перенос WeakHashMap в синхронизированную карту правильно для того, что вы хотите сделать, поскольку сборщик мусора может изменять weakreferences напрямую в любое время, минуя оболочку синхронизированной карты?Я думаю, что WeakHashMap действительно работает только в однопоточной модели.
Как упоминалось выше, документация для WeakHashMap на https://docs.oracle.com/javase/7/docs/api/java/util/WeakHashMap.html конкретно говорится:
"Синхронизированная WeakHashMap может быть создана с использованием Collections.Метод synchronizedMap"
Что подразумевает для меня, что этот метод должен работать в тандеме с поведением сборщика мусора (если только документация не содержит ошибок!)
Если вы используете Java 7 и выше, этот вариант использования решается потокобезопасным способом с ClassValue
https://docs.oracle.com/javase/7/docs/api/java/lang/ClassValue.html Если вам требуется использование remove
, тщательно подумайте о параллелизме и внимательно прочитайте документ.
Если вы используете Java 6 или ниже.Нет, вы должны синхронизировать WeakHashMap.
По-прежнему ли обертывание WeakHashMap в синхронизированную карту работает корректно для того, что вы хотите сделать, поскольку сборщик мусора может изменять weakreferences напрямую в любое время, минуя оболочку синхронизированной карты?Я думаю, что WeakHashMap действительно работает только в однопоточной модели.