wait() and sleep()

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):

void wait(long timeout)

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.

void wait(long timeout, int nanos)

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) {}
        }
    }
}

Get Java Threads, Second Edition now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.