В чем разница между AtomicReference<Integer> и AtomicInteger?
Я не понимаю разницы между этими двумя:
AtomicReference<Integer> atomicReference = new AtomicReference<>(1);
против
AtomicInteger atomicInteger = new AtomicInteger(1);
Может кто-нибудь вообще сказать, когда использовать AtomicReference? Надеюсь, кто-нибудь может мне помочь. Благодарю.
4 ответа
Очень важным отличием является то, что методы compareAndSet
а также weakCompareAndSet
имеют различную семантику для AtomicReference<Integer>
чем они делают для AtomicInteger
, Это потому что с AtomicReferece<Integer>
эти методы используют ==
для сравнения и два Integer
объекты могут быть равны, не будучи ==
, С AtomicInteger
, сравнение имеет целочисленное равенство значений, а не ссылочную идентичность.
Как уже отмечали другие, AtomicInteger
имеет дополнительные функции, недоступные с AtomicReference<Integer>
, Также, AtomicInteger
продолжается Number
так что наследует все Number
методы (doubleValue()
и т. д.) и может использоваться всякий раз, когда Number
ожидается.
Не большая разница, если вы используете только set(...)
а также get()
но AtomicInteger
имеет некоторые другие методы, такие как incrementAndGet()
которые работают только для целых чисел.
AtomicReference
оборачивает volatile Object
в то время как AtomicInteger
оборачивает volatile int
поэтому он может выполнять целочисленные методы, включая методы увеличения, уменьшения и добавления. AtomicInteger
также расширяется Number
что означает, что он поддерживает doubleValue()
, longValue()
и др. методы.
AtomicReference
является универсальным классом, который может ссылаться на произвольные типы.
Если вы хотите использовать экземпляр вашего собственного класса атомарно, вам нужно AtomicReference<V>
,
AtomicInteger
специализированная версия, которая содержит целые числа Это более эффективно (без ненужного бокса), и имеет полезные методы, такие как incrementAndGet()
,
Как отмечают другие, AtomicReference<Integer>
использует == для сравнения объектов. Следовательно,compareAndSet(expect, update)
обновит вашу первоначальную ссылку, только если expect
равно объекту, сохраненному в вашей атомарной ссылке с использованием ==.
Это может привести к некоторым хитрым ошибкам, если вы используете AtomicReference
для числовых типов, т.е. Integer
или же Long
, Обратите внимание, что статические конструкторы этих классов (например, Integer.valueOf(int value)
) возвращать внутренне кэшированные объекты для небольших значений. Другими словами, два разных вызова Integer.valueOf(5)
возвращает тот же экземпляр Integer
, Это безопасно, так как классы неизменны. В результате, если вы используете AtomicReference<Integer>
в то время как вы действительно должны использовать AtomicInteger
, это может хорошо работать для этих небольших чисел, потому что == может фактически сравнивать одни и те же объекты. Хуже только тогда, когда вы начинаете работать с более высокими значениями в какой-то момент.
Подводя итоги, используя AtomicInteger
гораздо безопаснее для числовых операций:)