假设对象中的一个字段根据一个线程的操作,从 null 到非 null 以及来回变化等。
每当第二个线程碰巧获得非空值时,它就会惰性地采取一些操作。特别是,第二个线程应等待,直到该值切换为非空。如果它超出了等待范围,我想确保它手中有一个非空值。
这看起来不像队列情况,因为第二个线程不会拿走该元素,它只是在有可用元素时使用它。
它也不适合信号量使用,因为它同样不会.acquire()
许可。
相反,它让人想起内置等待的比较和获取,但这似乎不存在。
在java.util.concurrent
中是否有一个我想识别的预定义设备。如何做到这一点?
This类似,但没有公认的答案或对这里有帮助的答案。
最佳答案
这是一个依赖 ReentrantLock
来管理 volatile
字段的实现。这很大程度上借用了双重检查锁定习惯,但读取操作不是创建值本身,而是等待条件来发出已设置值的信号。
get()
方法重载了接受超时的版本。两个版本都是可中断的。
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class BlockingRef<V> {
private final Lock lock = new ReentrantLock(true);
private final Condition signal = lock.newCondition();
private volatile V value;
public BlockingRef() {
this(null);
}
public BlockingRef(V initialValue) {
this.value = initialValue;
}
public final void set(V value) {
lock.lock();
try {
this.value = value;
signal.signalAll();
} finally {
lock.unlock();
}
}
public final V get() throws InterruptedException {
V result = value;
if (result == null) {
lock.lockInterruptibly();
try {
for (result = value; result == null; result = value)
signal.await();
} finally {
lock.unlock();
}
}
return result;
}
public final V get(long time, TimeUnit unit)
throws TimeoutException, InterruptedException
{
V result = value;
if (result == null) {
long start = System.nanoTime();
if (!lock.tryLock(time, unit)) throw new TimeoutException();
try {
time = unit.toNanos(time);
for (result = value; result == null; result = value) {
long wait = time - (System.nanoTime() - start);
if (wait <= 0) throw new TimeoutException();
signal.await(wait, TimeUnit.NANOSECONDS);
}
} finally {
lock.unlock();
}
}
return result;
}
@Override
public String toString() {
return String.valueOf(value);
}
}
关于java - 如果非空则使用值,否则等待并原子地获取它,在循环中重复,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39438188/