Skip to content
Advertisement

Thread not awake when timed wait elapsed in java

I am study wait(long timeout) in java,and in the offcial document I found below description:

  • Some other thread invokes the notify method for this object and thread T happens to be arbitrarily chosen as the thread to be awakened.
  • Some other thread invokes the notifyAll method for this object.
  • Some other thread interrupts thread T.
  • The specified amount of real time has elapsed, more or less. If timeout is zero, however, then real time is not taken into consideration and the thread simply waits until notified.

The last item said The specified amount of real time has elapsed, more or less,so in my option if we invoke wait(time),when time elapsed,the thread should awake itself.

So I wrote below code for test.

public static void testTimedWait() {
    Object lock = new Object();
    DateTimeFormatter df = DateTimeFormatter.ofPattern("HH:mm:ss:SSS");
    new Thread(() -> {
        synchronized (lock) {
            try {
                System.out.println(LocalTime.now().format(df) + "t" + Thread.currentThread().getName() + " start to run");
                lock.wait(5_000);
                System.out.println(LocalTime.now().format(df) + "t" + Thread.currentThread().getName() + " finished running");
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }, "thread-1").start();
    new Thread(() -> {
        synchronized (lock) {
            try {
                System.out.println(LocalTime.now().format(df) + "t" + Thread.currentThread().getName() + " start to run");
                Thread.sleep(10_000);
                //lock.notifyAll();
                System.out.println(LocalTime.now().format(df) + "t" + Thread.currentThread().getName() + " finished running");
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }, "thread-2").start();
}

In Thread-1 I invoke lock.wait(5_000) and in Thread-2 I invoke Thread.sleep(10_000),so once the code start to run,Thread-1 should awake after 5 seconds and Thread-2 should awake after 10 seconds theoretically.

When we run code above,the result listed like below:

Thread-1 doesn’t awake after 5 seconds!

Could someone help to understand why thread not awake when the wait time has elasped,thanks in advance! enter image description here


Update1:

Change code as below:

public static void testTimedWait() {
    Object lock = new Object();
    DateTimeFormatter df = DateTimeFormatter.ofPattern("HH:mm:ss:SSS");
    new Thread(() -> {
        synchronized (lock) {
            try {
                System.out.println(LocalTime.now().format(df) + "t" + Thread.currentThread().getName() + " start to run");
                lock.wait(20_000);
                System.out.println(LocalTime.now().format(df) + "t" + Thread.currentThread().getName() + " finished running");
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }, "thread-1").start();
    new Thread(() -> {
        synchronized (lock) {
            try {
                System.out.println(LocalTime.now().format(df) + "t" + Thread.currentThread().getName() + " start to run");
                Thread.sleep(10_000);
                //lock.notifyAll();
                System.out.println(LocalTime.now().format(df) + "t" + Thread.currentThread().getName() + " finished running");
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }, "thread-2").start();
}

Above code make Thread-1 wait for 20 seconds and Thread-2 sleep for 10 seconds,Thread-1 will awake after the specific seconds.Now it works as expected.

enter image description here


Update2: Remove Thread-2

public static void testTimedWait() {
    Object lock = new Object();
    DateTimeFormatter df = DateTimeFormatter.ofPattern("HH:mm:ss:SSS");
    new Thread(() -> {
        synchronized (lock) {
            try {
                System.out.println(LocalTime.now().format(df) + "t" + Thread.currentThread().getName() + " start to run");
                lock.wait(20_000);
                System.out.println(LocalTime.now().format(df) + "t" + Thread.currentThread().getName() + " finished running");
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }, "thread-1").start();
}

The test result is also working as expected.But I still do not know why Thread-1 not awake when it wait longer then Thread-2

enter image description here

Advertisement

Answer

Your threads are both synchronized on the same object. Therefore, you have to pay attention to the methods’s effect on synchronization:

  • Object.wait(…):

    • “This method causes the current thread (referred to here as T) to place itself in the wait set for this object and then to relinquish any and all synchronization claims on this object.”
    • “The thread T is then removed from the wait set for this object and re-enabled for thread scheduling. It competes in the usual manner with other threads for the right to synchronize on the object; once it has regained control of the object, all its synchronization claims on the object are restored to the status quo ante – that is, to the situation as of the time that the wait method was invoked.”
  • Thread.sleep(long): “The thread does not lose ownership of any monitors.

So, when the first thread invokes wait, it releases the lock, which is the only way how the second thread could even enter the synchronized block. Then, the second thread calls sleep, which does not release the lock. Therefore, after the time has elapsed, the first thread can not proceed, as it can’t acquire the lock, the second thread is still holding.

Of course, if you extend the first thread’s waiting time, to wait longer than the second thread, the lock has been released in the meanwhile and the first thread can proceed immediately after the waiting time.

User contributions licensed under: CC BY-SA
2 People found this is helpful
Advertisement