An AtomicBoolean
is great for this, and in particular its compareAndSet
method. That method takes two arguments: an "expected" value and a new value. It atomically does three things: (a) checks whether the current value is equal to the expected value, (b) if so, updates the current value to the new value, and (c) returns true iff that update happened (that is, if the expected and old values were the same).
private static final AtomicBoolean hasRun = new AtomicBoolean(false);
...
if (hasRun.compareAndSet(false, true)) {
// your code here
}
This code will check to see if hasRun
has a "false" value (which is its initial state). If so, it'll set itself to "true" and run if
's block; otherwise, it'll keep its current state and not run the if
's block. Crucially, the check-and-set is atomic (as the class name implies), meaning that no two threads can simultaneously see a false value; one of them will see the false value and set it to true, without the other thread being able to "sneak in" between those two actions.