Using wait(), notify() and notifyAll() in Java (ctd)
On the previous page, we showed how to create a very simple connection pool, in
which a thread could call a getConnection() method. If no connection was currently
available, this method would wait for one to become available. A downside of it is that if
no connection became avaialable, the method would essentially wait forever. A functionality
that we often want in this case is to say "wait for up to n seconds, else give
up". And we can get that with a timed wait.
In a timed wait, we pass in a parameter to the wait() method
specifying how long we want to wait for. Up to Java 1.4, the maximum wait time is specified
in milliseconds. So, the following would wait for up to 3 seconds:
// Wait for up to 3 seconds for a connection
From Java 5 onwards, an extra parameter allows you to specify the wait time down to
the nanosecond. In reality, no mainstream operating system provides that level of granularity
(to within a few milliseconds, or multiples of the interrupt period– often 10 milliseconds–
is typical). But in principle at least, some real-time operating systems may provide
more granularity than the millisecond.
So, when we're woken up, how do we know if it was because we were notified or because
we timed out? The answer is, we don't know why we were woken up. Just as actually
we don't even with the non-timed wait (in principle, the OS could just wake us up for a laugh1).
So in a case such as this, if we're woken up and there is no connection in the list, we need
to explicitly time how long we were waiting (e.g. via System.currentTimeMillis())
and decide whether to give up or wait again.
On the next pages we look at:
1. One reason that this might happen would be if an OS only implemented 'notify all'
functionality, and not single-thread notify. In this case, a JVM might be forced to
implement notify() as a 'notify all' action. According to the spec, this
would be a legal JVM implementation.
(In reality, I believe all
mainstream OS's provide both calls.)