I wrote myself a Doze
class for this.
It avoids using Thread.sleep
completely by using a BlockingQueue
internally. It is simple to use, as the main
method shows. You just doze
for a time and if anyone calls the Doze.wakeup()
method you get woken up.
You will need to arrange for your Doze
object to be available to the package that updates the property. On update it should call its wakeup()
.
/**
* Use one of these to doze for a certain time.
*
* The dozing is fully interruptable.
*
* Another thread can stop the caller's doze with either a wakeup call or an abort call.
*
* These can be interpreted in any way you like but it is intended that a Wakeup is
* interpreted as a normal awakening and should probably be treated in exactly the
* same way as an Alarm. An Abort should probably be interpreted as a suggestion
* to abandon the proces.
*/
public class Doze {
// Special alarm messages.
public enum Alarm {
// Standard timeout.
Alarm,
// Just wake from your doze.
Wakeup,
// Abort the whole Doze process.
Abort;
}
// My queue to wait on.
private final ArrayBlockingQueue<Alarm> doze = new ArrayBlockingQueue<>(1);
// How long to wait by default.
private final long wait;
public Doze(long wait) {
this.wait = wait;
}
public Doze() {
this(0);
}
public Alarm doze() throws InterruptedException {
// Wait that long.
return doze(wait);
}
public Alarm doze(long wait) throws InterruptedException {
// Wait that long.
Alarm poll = doze.poll(wait, TimeUnit.MILLISECONDS);
// If we got nothing then it must be a normal wakeup.
return poll == null ? Alarm.Alarm : poll;
}
public void wakeup() {
// Just post a Wakeup.
doze.add(Alarm.Wakeup);
}
public void abort() {
// Signal the system to abort.
doze.add(Alarm.Abort);
}
// Demo of use.
public static void main(String[] args) throws InterruptedException {
// Doze for 1 second.
final Doze d = new Doze(1 * 1000);
// Start a dozing thread.
new Thread(new Runnable() {
@Override
public void run() {
try {
Alarm a = d.doze();
// Wait forever until we are aborted.
while (a != Alarm.Abort) {
System.out.println("Doze returned " + a);
a = d.doze();
}
System.out.println("Doze returned " + a);
} catch (InterruptedException ex) {
// Just exit on interrupt.
}
}
}).start();
// Wait for a few seconds.
Thread.sleep(3000);
// Wake it up.
d.wakeup();
// Wait for a few seconds.
Thread.sleep(3000);
// Abort it.
d.abort();
}
}