|
||||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |
java.lang.Object | +--javatools.thread.ThreadSleeper
Allows a thread to sleep when there is nothing to do. This class is designed to be used by threads which loop around doing work but which need to sleep when there is nothing to do. Other threads need to notify this worker thread when work is available. This is a tricky threading problem which is why it is made into a separate class. The reason it is tricky is that there are potential race conditions between another thread setting a flag that there is something to do, checking the flag and going to sleep if there is nothing to do. The java synchronized keyword doesn't seem to be of help here - We can't put a synchronized block around code to check a flag and go to sleep, because the sleep() would cause the synchronized lock to block other threads trying to notify us of new work.
The semantics of waitForWork() is this: waitForWork() will sleep if notifyOfWork() has not been called anytime between the end of the previous call to waitForWork and now. Depending on when wakeup is called it is possible that occasionally waitForwork might not sleep when it is supposed to, but it is guaranteed that waitForWork will never sleep when it is not supposed to. So the calling program must handle the case of there being nothing to do but it is guaranteed that we won't sleep forever when there is something to do. The goal is to sleep forever when there is nothing to do, but we are prepared to accept the occasional case of not sleeping - briefly - when there is nothing to do. That's ok, the next time through your application's main loop the sleep will activate correctly if there is nothing to do. That is a minor race condition we can't avoid, but sleeping when there is work to do is a flaw we MUST avoid.
The interesting thing about the class is that it coordinates threads without the use of the synchronized java keyword. The reason is that using synchronized with methods that sleep must be a bad thing - it would hang any other thread trying to synchronize on the same lock. So we use the following method. It is quite hard (even for the author) to prove in your mind that this code works because the threading problems posed are tricky. The key part is that while waitForWork sets the doSleep flag before checking the wakeupTicker, the notifyOfWork method does the reverse - it increments the wakeupTicker before checking the doSleep flag. Then the notifyOfWork will keep looping till its job is done. However because it calls yield() it is unlikely to loop many times. BUGS: I think I shouldn't have written this class. It performs the same behaviour as Object.wait() and Object.notify. Needs further investigation whether to obliterate this class.
Field Summary | |
(package private) boolean |
doSleep
|
(package private) long |
oldWakeupTicker
|
(package private) java.lang.Thread |
t
The thread that may need to sleep. |
(package private) long |
wakeupTicker
This is a running counter that gets incremented when work becomes available. |
Constructor Summary | |
ThreadSleeper()
Create a ThreadSleeper |
Method Summary | |
void |
notifyOfWork()
Notify the thread that work is available. |
void |
waitForWork()
Same as |
void |
waitForWork(long time)
Possibly sleep until new work is available. |
Methods inherited from class java.lang.Object |
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait |
Field Detail |
java.lang.Thread t
volatile boolean doSleep
volatile long wakeupTicker
volatile long oldWakeupTicker
Constructor Detail |
public ThreadSleeper()
Method Detail |
public void waitForWork()
except we potentially sleep forever.
public void waitForWork(long time)
time
- Description of Parameterpublic void notifyOfWork()
|
||||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |