java.util.concurrent.atomic.AtomicBoolean
没有可以原子地否定/反转值的方法吗?我可以用另一种方式吗?我错过了什么吗?
答案 0 :(得分:14)
年纪稍大......但并不觉得答案很棒。
必须完全不同意这不常见或仅在硬件中有用。您可能需要多个线程在单个变量上切换,具有相同的可能性...我使用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;
}
}
}
答案 1 :(得分:12)
我天真的实施是这样的:
boolean v;
do {
v=atomicBoolean.get();
} while(!atomicBoolean.compareAndSet(v, !v));
答案 2 :(得分:1)
书籍The CERT Oracle Secure Coding Standard for Java中建议的解决方案如下:
import java.util.concurrent.atomic.AtomicBoolean;
final class Flag {
private AtomicBoolean flag = new AtomicBoolean(true);
public void toggle() {
boolean temp;
do {
temp = flag.get();
} while(!flag.compareAndSet(temp, !temp));
}
}
答案 3 :(得分:0)
使用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;
}
答案 4 :(得分:0)
您可以使用AtomicBoolean.negate()
模拟AtomicInteger.getAndIncrement()
,并将偶数视为true
,将奇数视为false
。
应该忽略该数字的实际值,因此您不必关心整数溢出。
答案 5 :(得分:0)
如果您使用的是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()));
}
}
或者如果您想直接获得它...