Класс AtomicInteger защищает базовое значение int, предоставляя методы, которые выполняют атомарные операции над значением. Он не должен использоваться в качестве замены для класса Integer.
Класс AtomicInteger является частью пакета java.util.concurrent.atomic начиная с Java 1.5.
1. Создать, получить и установить значение AtomicInteger
Создание AtomicInteger осуществляется напрямую путем вызова конструктора. AtomicInteger предоставляет два метода для получения и установки значений своих экземпляров.
//Initial value is 0AtomicInteger atomicInteger = new AtomicInteger();//Initial value is 100AtomicInteger atomicInteger = new AtomicInteger(100);int currentValue = atomicInteger.get(); //100atomicInteger.set(1234); //Now value is 1234
2. Когда использовать AtomicInteger в Java
В реальной жизни нам понадобится AtomicInteger в двух случаях:
- Как атомарный счетчик, который используется несколькими потоками одновременно.
- В операциях сравнения и обмена для реализации неблокируемых алгоритмов.
2.1. AtomicInteger как атомарный счетчик
Для использования его в качестве счетчика класс AtomicInteger предоставляет несколько методов, которые выполняют операции сложения и вычитания атомарно.
- addAndGet() – атомарно добавляет заданное значение к текущему значению и возвращает новое значение после сложения.
- getAndAdd() – атомарно добавляет заданное значение к текущему значению и возвращает старое значение.
- incrementAndGet() – Атомарно увеличивает текущее значение на 1 и возвращает новое значение после увеличения. Эквивалентно операции ++i.
- getAndIncrement() – Атомарно увеличивает текущее значение и возвращает старое значение. Эквивалентно операции i++.
- decrementAndGet() – Атомарно уменьшает текущее значение на 1 и возвращает новое значение после уменьшения. Эквивалентно i- – операции.
- getAndDecrement() – Атомарно уменьшает текущее значение и возвращает старое значение. Эквивалентно операции – -i.
public class Main{public static void main(String[] args){AtomicInteger atomicInteger = new AtomicInteger(100);System.out.println(atomicInteger.addAndGet(2)); //102System.out.println(atomicInteger); //102System.out.println(atomicInteger.getAndAdd(2)); //102System.out.println(atomicInteger); //104System.out.println(atomicInteger.incrementAndGet()); //105System.out.println(atomicInteger); //105System.out.println(atomicInteger.getAndIncrement()); //105System.out.println(atomicInteger); //106System.out.println(atomicInteger.decrementAndGet()); //105System.out.println(atomicInteger); //105System.out.println(atomicInteger.getAndDecrement()); //105System.out.println(atomicInteger); //104}}
2.2. Сравнение и обмен операциями
Операция сравнения и обмена сравнивает содержимое ячейки памяти с заданным значением и, только если они одинаковы, изменяет содержимое этой ячейки памяти на заданное новое значение. Это делается как одна атомарная операция.
Атомарность гарантирует, что новое значение вычисляется на основе актуальной информации; если бы значение было обновлено другим потоком за это время, запись завершилась бы ошибкой.
Для поддержки операций сравнения и обмена этот класс предоставляет метод, который атомарно устанавливает значение на заданное обновленное значение, если текущее значение == ожидаемому значению.
boolean compareAndSet(int expect, int update)
Мы можем наблюдать множество случаев использования метода compareAndSet() в реальном времени в классах параллельных коллекций Java, таких как ConcurrentHashMap.
import java.util.concurrent.atomic.AtomicInteger;public class Main{public static void main(String[] args){AtomicInteger atomicInteger = new AtomicInteger(100);boolean isSuccess = atomicInteger.compareAndSet(100,110); //current value 100System.out.println(isSuccess); //trueisSuccess = atomicInteger.compareAndSet(100,120); //current value 110System.out.println(isSuccess); //false}}
Вывод программы.
truefalse
3. Заключение
Как обсуждалось выше, основное применение AtomicInteger — когда мы находимся в многопоточном контексте и нам нужно выполнить атомарные операции над значением int без использования ключевого слова synchronized.
Использование AtomicInteger столь же быстро и более читабельно, как и выполнение того же самого с использованием синхронизации.
Подробнее: Документация Java