Подтвердить что ты не робот

У AtomicBoolean нет метода negate()?

Не имеет ли java.util.concurrent.atomic.AtomicBoolean метода, который может атомически отрицать/инвертировать значение? Могу ли я сделать это по-другому? Я что-то пропустил?

4b9b3361

Ответ 1

Маленький старик... но на самом деле не чувствовал, что ответы были большими.

Необходимо полностью не согласиться с тем, что это не является обычным явлением или полезно только для аппаратного обеспечения. Вы можете захотеть, чтобы ряд потоков переключился на одну переменную с равным вероятностью... Я использовал AtomicLong для создания фальшивого логического. Это было принято из JMS MessageListener, что мне нужно было ответить на определенное сообщение в течение половины времени, а другой - на другую половину.

public class Mock {
    private static AtomicLong count = new AtomicLong(0);

    public boolean respond() {
        long currentCount = count.getAndIncrement();

        if (currentCount % 2 == 0) {
            return true;
        } else {
            return false;
        }
    }
}

Ответ 2

Моя наивная реализация будет следующей:

boolean v;
do {
  v=atomicBoolean.get();
} while(!atomicBoolean.compareAndSet(v, !v));

Ответ 4

Используя метод AtomicBoolean # compareAndSet() и цикл while вы можете реализовать метод для переключения значения AtomicBoolean в потоке - безопасный способ:

public static boolean negate(AtomicBoolean ab) {
    // get the oposite value
    boolean newVal = !ab.get();

    // try to set the new value if the current value is the oposite of the new value
    while (!ab.compareAndSet(!newVal, newVal)) {
        // if the value we try to set was already set in the mean-time
        // then toggle the new value and try again
        newVal = !newVal;
    }
    // return the value we finally could set
    return newVal;
}

Ответ 5

Вы можете эмулировать AtomicBoolean.negate(), используя AtomicInteger.getAndIncrement() и рассматривая четные числа как true а нечетные числа как false. Фактическое значение числа следует игнорировать, поэтому вам не нужно беспокоиться о целочисленных переполнениях.

Ответ 6

Если вы имеете дело с Java 9 или более поздней версии, я предлагаю:

    /**
     * Flip the AtomicBoolean.
     * Sets the boolean value to false if it is true, and to true if it is false
     * with memory effects as specified by {@link java.lang.invoke.VarHandle#setVolatile}.
     *
     * @param atomicBoolean atomicBoolean
     * @return new boolean value of AtomicBoolean
     * @see AtomicInteger#accumulateAndGet(int x, IntBinaryOperator accumulatorFunction)
     * @since 9
     */
    public static final boolean flip(AtomicBoolean atomicBoolean) {
        boolean prev = atomicBoolean.get(), next = false;
        for (boolean haveNext = false; ; ) {
            if (!haveNext) {
                next = !prev;
            }
            if (atomicBoolean.weakCompareAndSetVolatile(prev, next)) {
                return next;
            }
            haveNext = (prev == (prev = atomicBoolean.get()));
        }
    }

Или, если вы хотите получить это напрямую...

https://github.com/XenoAmess/commonx/blob/master/src/main/java/com/xenoamess/commonx/java/util/concurrent/atomic/AtomicBooleanUtilsx.java