Класс AtomicBoolean
Класс AtomicBoolean из пакета java.util.concurrent.atomic
предназначен для атомарной работы с логическим значением
в многопоточной среде. В отличие от обычной переменной
типа boolean, операции чтения и записи над объектом
AtomicBoolean выполняются атомарно, то есть без
промежуточных состояний, видимых другим потокам.
Это позволяет обойтись без явных блокировок synchronized
и избежать состояния гонки.
Класс предоставляет методы get и set
для чтения и записи значения, метод compareAndSet
для атомарной замены значения только при условии,
что текущее значение равно ожидаемому, а также методы
getAndSet, lazySet и weakCompareAndSet.
В конструктор можно передать начальное значение,
по умолчанию оно равно false.
Синтаксис
AtomicBoolean ab = new AtomicBoolean();
AtomicBoolean ab = new AtomicBoolean(initialValue);
ab.get();
ab.set(newValue);
ab.compareAndSet(expectedValue, newValue);
ab.getAndSet(newValue);
ab.lazySet(newValue);
ab.weakCompareAndSet(expectedValue, newValue);
Пример
Давайте создадим объект AtomicBoolean с начальным
значением false и прочитаем его через метод get:
import java.util.concurrent.atomic.AtomicBoolean;
public class Main
{
public static void main(String[] args)
{
AtomicBoolean ab = new AtomicBoolean(false);
System.out.println(ab.get());
}
}
Результат выполнения кода:
false
Пример
Давайте изменим значение через метод set
и выведем результат:
import java.util.concurrent.atomic.AtomicBoolean;
public class Main
{
public static void main(String[] args)
{
AtomicBoolean ab = new AtomicBoolean(false);
ab.set(true);
System.out.println(ab.get());
}
}
Результат выполнения кода:
true
Пример
Метод compareAndSet заменяет значение только
в том случае, если текущее значение равно ожидаемому.
Первый параметр - ожидаемое значение, второй - новое.
Метод возвращает true, если замена произошла:
import java.util.concurrent.atomic.AtomicBoolean;
public class Main
{
public static void main(String[] args)
{
AtomicBoolean ab = new AtomicBoolean(false);
boolean res = ab.compareAndSet(false, true);
System.out.println(res);
System.out.println(ab.get());
}
}
Результат выполнения кода:
true
true
Пример
Если ожидаемое значение не совпадает с текущим,
метод compareAndSet возвращает false
и значение не меняется:
import java.util.concurrent.atomic.AtomicBoolean;
public class Main
{
public static void main(String[] args)
{
AtomicBoolean ab = new AtomicBoolean(true);
boolean res = ab.compareAndSet(false, true);
System.out.println(res);
System.out.println(ab.get());
}
}
Результат выполнения кода:
false
true
Пример
Метод getAndSet атомарно устанавливает новое
значение и возвращает предыдущее:
import java.util.concurrent.atomic.AtomicBoolean;
public class Main
{
public static void main(String[] args)
{
AtomicBoolean ab = new AtomicBoolean(false);
boolean old = ab.getAndSet(true);
System.out.println(old);
System.out.println(ab.get());
}
}
Результат выполнения кода:
false
true
Пример
Класс AtomicBoolean удобно использовать как
флаг остановки для потока. Давайте запустим поток,
который выполняется, пока флаг равен false,
а затем остановим его из главного потока:
import java.util.concurrent.atomic.AtomicBoolean;
public class Main
{
public static void main(String[] args) throws InterruptedException
{
AtomicBoolean running = new AtomicBoolean(true);
Thread thread = new Thread(() -> {
int count = 0;
while (running.get())
{
count++;
}
System.out.println("stopped at " + count);
});
thread.start();
Thread.sleep(100);
running.set(false);
thread.join();
}
}
Результат выполнения кода:
"stopped at 12345678"
Смотрите также
-
класс
AtomicInteger,
который атомарно работает с целым числом -
класс
AtomicReference,
который атомарно работает со ссылкой на объект -
ключевое слово
volatile,
которое обеспечивает видимость переменной -
ключевое слово
synchronized,
которое обеспечивает взаимное исключение потоков