The
Object class also overloads the wait()
method to
allow it to take a timeout specified in milliseconds (though, as we
mentioned in Chapter 2, the timeout resolution may
not be as precise as one millisecond):
Waits for a condition to occur. However, if the notification has not
occurred in timeout
milliseconds, it returns
anyway. This is a method of the Object class and must be called from
a synchronized block or method.
Waits for a condition to occur. However, if the notification has not
occurred in timeout
milliseconds and
nanos
nanoseconds, it returns anyway. This is a
method of the Object class and must be called from a synchronized
block or method.
These methods are provided to support external events. In cases where
we are only concerned with a notification arriving, we normally do
not use these methods. However, notifications can be dependent on
external conditions, in which case we are also concerned with when a
notification arrives. A timeout may be needed in case those
conditions do not occur. As an example, we might write a program that
connects to a stock feed server. The program may be willing to wait
30 seconds to connect to the server (that is, to satisfy the
condition of being connected); if the connection does not occur
within 30 seconds, the program may try to contact a backup server.
We’d accomplish this by calling the
wait(30000)
method in our program.
We may still add a timeout when we know that a condition will
eventually be satisfied so that we can accomplish other tasks. For
example, let’s assume that we needed to do other tasks in our
getBusyFlag()
method:
public synchronized void getBusyFlag() {
while (tryGetBusyFlag() == false) {
wait(100);
doSomethingElse();
}
}
In this version of getBusyFlag()
, we
wait()
for the notification for up to 100
milliseconds. If this notification does not arrive within the
requested time, we are awakened anyway. This is actually a very
contrived example: we could have easily created another thread that
does something else.
If we know that the notification will never arrive, what is
the difference between wait(long) and
sleep(long)?
Let’s say, for example, we do not use the
notify()
method on an object. Then, in theory,
there is no reason to wait()
on the object.
However, the wait(long)
method does have an
extra benefit: it behaves like the sleep(long)
method of the Thread class, except that it also releases and
reacquires a lock. This means that if we are not using the wait and
notify mechanism, we can still use the
wait(long)
method as a way of sleeping without
holding the lock. For example, suppose we have the following class:
public class WaitExample { public synchronized void ProcessLoop() { processOne(); try { wait(1000); } catch (Exception e) {} processTwo(); } }
The WaitExample class is a simple example of a method that needs to
sleep for one second between two distinct operations, during which
time it must give up the lock. If we had to code the same class
without using the wait(long)
method, it would
add extra complexity:
public class WaitExample { public void ProcessLoop() { synchronized (this) { processOne(); } try { Thread.sleep(1000); } catch (Exception e) {} synchronized (this) { processTwo(); } } }
As we said, this is a simple example: imagine if we had to code the
following class without the use of the
wait(long)
method:
public class WaitExample { public synchronized void ProcessLoop() { processOne(); for (int i=0; i<50; i++) { processTwo(); try { wait(1000); } catch (Exception e) {} } } }