1

I was trying to understand more about Thread.interrupt(), and so I wrote the following codes.

public class Test {

    private Object object = new Object();

    Runnable thread1 = () -> {
        synchronized (object) {
            System.out.println(System.currentTimeMillis() + " - Thread1 inside synchronized block");
            try {
                object.wait();
                System.out.println(System.currentTimeMillis() + " - Thread1 after wait()");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(System.currentTimeMillis() + " - Thread1 ending");
        }
    };

    Runnable thread2 = () -> {
        synchronized (object) {
            System.out.println(System.currentTimeMillis() + " - Thread2 inside synchronized block");
            try {
                Thread.sleep(2000);
                System.out.println(System.currentTimeMillis() + " - Thread2 after sleep");
                object.notify();
                System.out.println(System.currentTimeMillis() + " - Thread2 after notify()");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(System.currentTimeMillis() + " - Thread2 ending");
        }
    };

    public void run() {
        Thread t1 = new Thread(thread1);
        Thread t2 = new Thread(thread2);
        t1.start();
        t2.start();
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        t1.interrupt();
    }

    public static void main(String[] args) {
        new Test().run();
    }

}

I couldn't understand the result. Firstly, why is the exception stack trace not showing on the third line of the output? The first thread was interrupted while the second thread was still sleeping, so the exception should occur before the second thread woke up. Secondly, why is "Thread 1 ending" showing up before the stack trace?

1643099950931 - Thread1 inside synchronized block
1643099950947 - Thread2 inside synchronized block
1643099952947 - Thread2 after sleep
1643099952947 - Thread2 after notify()
1643099952947 - Thread2 ending
1643099952947 - Thread1 ending
java.lang.InterruptedException
    at java.base/java.lang.Object.wait(Native Method)
    at java.base/java.lang.Object.wait(Object.java:328)
    at com.ocbc.ms.Test.lambda$new$0(Test.java:13)
    at java.base/java.lang.Thread.run(Thread.java:834)
Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
user3573403
  • 1,780
  • 5
  • 38
  • 64

1 Answers1

3

From the documentation of Thread.wait (relevant part highlighted in bold):

Causes the current thread to wait until it is awakened, typically by being notified or interrupted, or until a certain amount of real time has elapsed.

...

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.

Thread T then becomes disabled for thread scheduling purposes and lies dormant until one of the following occurs:

  • ...

  • Some other thread interrupts thread T.

  • ...

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 T then returns from the invocation of the wait method. Thus, on return from the wait method, the synchronization state of the object and of thread T is exactly as it was when the wait method was invoked.

In other words, when thread 1 is interrupted by the main thread, it still has to wait for thread 2 to finish to relinquish its lock, and only then thread 1 will regain control of the lock and continue.

M A
  • 71,713
  • 13
  • 134
  • 174
  • I think I understand the doc. But I still don't understand why the stack trace is coming after the "Thread1 ending". – user3573403 Jan 25 '22 at 09:28
  • @user3573403 This is actually a different issue related to std output and error streams in Java discussed [here](https://stackoverflow.com/questions/31501829/stack-trace-is-not-printed-in-proper-order-with-other-messages-on-console) and [here](https://stackoverflow.com/questions/1883321/system-out-println-and-system-err-println-out-of-order). – M A Jan 25 '22 at 09:49