Класс AtomicInteger
Класс AtomicInteger из пакета java.util.concurrent.atomic
предназначен для атомарной работы с целочисленным значением.
Все его операции выполняются как единое неделимое действие,
что делает класс безопасным при использовании из нескольких потоков
без внешней синхронизации. Внутри класса значение хранится в поле
типа int, а доступ к нему осуществляется через
низкоуровневые атомарные инструкции процессора (CAS - compare-and-swap).
Основные методы класса: get возвращает текущее значение,
set устанавливает новое значение,
incrementAndGet увеличивает значение на единицу и возвращает результат,
decrementAndGet уменьшает значение на единицу и возвращает результат,
addAndGet прибавляет переданное число и возвращает результат,
getAndIncrement возвращает текущее значение и затем увеличивает его,
compareAndSet атомарно сравнивает значение с ожидаемым и,
если они равны, устанавливает новое.
Синтаксис
AtomicInteger name = new AtomicInteger(initialValue);
name.get();
name.set(newValue);
name.incrementAndGet();
name.decrementAndGet();
name.addAndGet(delta);
name.getAndIncrement();
name.compareAndSet(expectedValue, newValue);
Пример
Давайте создадим счётчик на основе AtomicInteger
и увеличим его значение несколько раз:
import java.util.concurrent.atomic.AtomicInteger;
public class Main
{
public static void main(String[] args)
{
AtomicInteger counter = new AtomicInteger(0);
counter.incrementAndGet();
counter.incrementAndGet();
counter.addAndGet(5);
System.out.println(counter.get());
}
}
Результат выполнения кода:
7
Пример
Давайте проверим работу метода compareAndSet.
Он вернёт true только если текущее значение
совпадает с ожидаемым:
import java.util.concurrent.atomic.AtomicInteger;
public class Main
{
public static void main(String[] args)
{
AtomicInteger value = new AtomicInteger(10);
boolean res1 = value.compareAndSet(10, 20);
boolean res2 = value.compareAndSet(10, 30);
System.out.println(res1);
System.out.println(res2);
System.out.println(value.get());
}
}
Результат выполнения кода:
true
false
20
Пример
Давайте запустим несколько потоков, которые одновременно увеличивают общий счётчик. Благодаря атомарности итоговое значение будет корректным:
import java.util.concurrent.atomic.AtomicInteger;
public class Main
{
public static void main(String[] args) throws InterruptedException
{
AtomicInteger counter = new AtomicInteger(0);
Runnable task = () -> {
for (int i = 0; i < 1000; i++)
{
counter.incrementAndGet();
}
};
Thread t1 = new Thread(task);
Thread t2 = new Thread(task);
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println(counter.get());
}
}
Результат выполнения кода:
2000
Смотрите также
-
метод
get,
который возвращает текущее значение -
метод
set,
который устанавливает новое значение -
метод
incrementAndGet,
который увеличивает значение на единицу -
метод
compareAndSet,
который атомарно сравнивает и устанавливает значение