Интересная проблема. Вот одно из решений моей головы. Имейте номер версии вместе со значением, которое изменяется. Всякий раз, когда значение обновляется, номер версии также увеличивается, поэтому объекты ValueWatcher
могут затем проверить, увеличилась ли версия, означающая, что произошло изменение.
Edit:
Первоначально у меня был AtomicLong
, но я краду идею обертки от @John Vint.
private final VersionValue versionValue = new VersionValue();
public void setValue(int value) {
synchronized (monitor) {
versionValue.value = value;
versionValue.version++;
monitor.notifyAll();
}
}
private class ValueWatcher {
private long localVersion = 0;
public int waitForValue() {
synchronized (monitor) {
while (true) {
if (localVersion < versionValue.version) {
// NOTE: the value might have been set twice here
localVersion = versionValue.version;
return versionValue.value;
}
monitor.wait();
}
}
}
}
private static class VersionValue {
int value;
long version;
}
Кроме того, хотя возможны ложные пробуждения, важно помнить, что текст:
Всегда вызывайте wait внутри цикла, который проверяет ожидаемое условие. Не думайте, что прерывание было для конкретного условия, которое вы ожидали, или что условие все еще выполняется.
Больше о гоночных условиях и моделях производитель / потребитель, чем о ложных пробуждениях. См. мою страницу здесь об этом .