16

I have a thread which has an incoming job queue (a LinkedList containing job descriptions). The thread blocks with wait() on the queue when there's no job to work on. An external job dispatcher object awakes it with notify() when it places new jobs on the queue.

At shutdown of my program i call interrupt() on the Thread. This raises InterruptedException when the Thread awaits for jobs in wait(). My question is: what will happen if i interrupt the Thread while it's not blocking but doing some kind of work, the processed item was the last in the queue (so queue is now empty) and execution pasts the isInterrupted() check before the interrupted flag is set so it calls wait() again? Will it throw an InterruptedException because the interrupted flag has already been set or the thread waits forever because new jobs will never arrive to the queue and there's no one to interrupt the wait?

NagyI
  • 5,907
  • 8
  • 55
  • 83

3 Answers3

16

yes, your interrupted thread will throw an InterruptedException upon calling wait(). this is pretty simple to test for yourself.

public class TestInt {
    public static void main(String[] args) throws Exception
    {
        Thread.currentThread().interrupt();

        synchronized(TestInt.class) {
            TestInt.class.wait();
        }    
    }    
}

also, note the javaodc for Object.wait():

InterruptedException - if any thread interrupted the current thread before or while the current thread was waiting for a notification. The interrupted status of the current thread is cleared when this exception is thrown.

jtahlborn
  • 52,909
  • 5
  • 76
  • 118
  • I like this answer best, for conciseness. The API specs do have the details you need to answer this question, and the code snippet above does verify it but for a plain summary of the answer I would say: a code in `otherThread` can call `myThread.interrupt()` _before_ myThread enters `wait()`. In `myThread`, a try-catch clause in around that `wait()` will catch the `InterruptedException`. However, if `myObj.notify()` is called in `otherThread` before the `wait()` in `myThread`, the `wait()` will not see it. – PMorganCA Jun 11 '13 at 14:12
  • Promoting this to answer since it contains sample code which explains the behaviour more clearly. – NagyI May 07 '15 at 07:35
14

Read the API specifications for Thread.interrupt() -

Interrupts this thread.

Unless the current thread is interrupting itself, which is always permitted, the checkAccess method of this thread is invoked, which may cause a SecurityException to be thrown.

If this thread is blocked in an invocation of the wait(), wait(long), or wait(long, int) methods of the Object class, or of the join(), join(long), join(long, int), sleep(long), or sleep(long, int), methods of this class, then its interrupt status will be cleared and it will receive an InterruptedException.

If this thread is blocked in an I/O operation upon an interruptible channel then the channel will be closed, the thread's interrupt status will be set, and the thread will receive a ClosedByInterruptException.

If this thread is blocked in a Selector then the thread's interrupt status will be set and it will return immediately from the selection operation, possibly with a non-zero value, just as if the selector's wakeup method were invoked.

If none of the previous conditions hold then this thread's interrupt status will be set.

Interrupting a thread that is not alive need not have any effect.

So, all that will happen is the thread's interrupt status will be set.

EDIT

If you read the API specifications for Object.wait(), you'll see the following -

Throws:

InterruptedException - if any thread interrupted the current thread before or while the current thread was waiting for a notification. The interrupted status of the current thread is cleared when this exception is thrown.

mre
  • 43,520
  • 33
  • 120
  • 170
  • 1
    But what happens if the interrupted status gets set *after* that my code checks `isInterrupted()` in the loop (so it sees "okay, we are not interrupted yet" so continues) and `wait()` gets called again with the interrupted status already set? I guess you mean from this it follows that it'll deadlock my application at shutdown, if i `join()` with this thread. If so, how can i avoid this? – NagyI Jul 14 '11 at 19:46
  • @Nagyl, I believe it will throw an `InterruptedException` when it attempts to invoke `wait()`. – mre Jul 14 '11 at 19:55
  • 1
    @Nagyl, If such a scenario occurs and you still encounter problems, it's probably because when you catch the `InterruptedException` on the `wait()`, you'll need to propagate the exception (i.e. `Thread.currentThread().interrupt()`), since the interrupted status will be cleared. – mre Jul 14 '11 at 20:02
  • Actually i've not yet encountered this problem within my project. I've just wondered about the possible errors while writing the code and i couldn't find the answer for this case by myself. The interrupt propagation is again a good thing to know, thanks! – NagyI Jul 14 '11 at 20:06
2

Though this is quite an old question, but I would want to add that if you call Thread.currentThread().interrupt() method during lock.wait() (while thread is in a WAITING state), it doesn't mean that the thread will internally have InterruptedException thrown immediately, first thread will get in the BLOCKED state (it becomes awakened as with lock.notify()/notifyAll() call from another thread, that allows it to compete for a shared lock) with interruption flag set to true, maybe after some period of time only after acquiring lock again (sometimes quite considerable amount of time) it can throw an InterruptedException (without lock it cannot proceed, even handling an exception).

package com.company;

public class Main {

    public static void main(String[] args) {
        final Object lock = Main.class;

        // three simple threads
        Thread th1 = new Thread(() -> {
            synchronized (lock) {
                for (int i = 0; i < 15; i++) {
                    sleepWithoutException(100);
                    System.out.println("th1 is doing some job!");
                }
            }
        });

        Thread th2 = new Thread(() -> {
            synchronized (lock) {
                for (int i = 0; i < 15; i++) {
                    sleepWithoutException(100);
                    System.out.println("th2 is doing some job!");
                }
            }
        });

        Thread th3 = new Thread(() -> {
            synchronized (lock) {
                for (int i = 0; i < 15; i++) {
                    sleepWithoutException(100);
                    System.out.println("th3 is doing some job!");
                }
            }
        });

        // thread which will be in WAITING state after 1 second
        Thread th4 = new Thread(() -> {
            synchronized (lock) {
                try {
                    sleepWithoutException(500);
                    lock.wait();
                    System.out.println("Continued");
                } catch (InterruptedException e) {
                    System.out.println("interrupted! " + e);
                    System.exit(1);
                }
            }
        });


        // execution
        th4.start();

        sleepWithoutException(100);

        th1.start();
        th2.start();
        th3.start();

        // thread which will monitor states of other threads
        new Thread(() -> {
            long start = System.currentTimeMillis();
            for (int i = 0; i < 1000_000; i++) {
                sleepWithoutException(100);
                System.out.println("-------------------------------------------------");
                System.out.println("step: " + i + " , timeElapsed: " + (System.currentTimeMillis() - start));
                if (i == 10) {
                    th4.interrupt();
                }
                System.out.println(
                        th1.getState() + " " + th1.isInterrupted() + "\n" +
                                th2.getState() + " " + th2.isInterrupted() + "\n" +
                                th3.getState() + " " + th3.isInterrupted() + "\n" +
                                th4.getState() + " " + th4.isInterrupted()
                );
            }
        }).start();


    }

    public static void sleepWithoutException(long time) {
        try {
            Thread.sleep(time);
        } catch (InterruptedException e) {
            System.out.println("fallen in sleep" + e);
        }
    }
}

see log below, as you can see other threads continue to work while th4 in BLOCKING state with flag isInterrupted is set to true (after a call of Thread.currentThread().interrupt() method)

-------------------------------------------------
step: 0 , timeElapsed: 101
BLOCKED false
BLOCKED false
BLOCKED false
TIMED_WAITING false
-------------------------------------------------
step: 1 , timeElapsed: 201
BLOCKED false
BLOCKED false
BLOCKED false
TIMED_WAITING false
-------------------------------------------------
step: 2 , timeElapsed: 301
BLOCKED false
BLOCKED false
BLOCKED false
TIMED_WAITING false
-------------------------------------------------
step: 3 , timeElapsed: 401
BLOCKED false
BLOCKED false
TIMED_WAITING false
WAITING false
th3 is doing some job!
-------------------------------------------------
step: 4 , timeElapsed: 502
BLOCKED false
BLOCKED false
TIMED_WAITING false
WAITING false
th3 is doing some job!
-------------------------------------------------
step: 5 , timeElapsed: 602
BLOCKED false
BLOCKED false
TIMED_WAITING false
WAITING false
th3 is doing some job!
-------------------------------------------------
step: 6 , timeElapsed: 703
BLOCKED false
BLOCKED false
TIMED_WAITING false
WAITING false
th3 is doing some job!
-------------------------------------------------
step: 7 , timeElapsed: 803
BLOCKED false
BLOCKED false
TIMED_WAITING false
WAITING false
th3 is doing some job!
-------------------------------------------------
step: 8 , timeElapsed: 904
BLOCKED false
BLOCKED false
TIMED_WAITING false
WAITING false
th3 is doing some job!
-------------------------------------------------
step: 9 , timeElapsed: 1004
BLOCKED false
BLOCKED false
TIMED_WAITING false
WAITING false
th3 is doing some job!
-------------------------------------------------
step: 10 , timeElapsed: 1105
BLOCKED false
BLOCKED false
TIMED_WAITING false
WAITING true
th3 is doing some job!
-------------------------------------------------
step: 11 , timeElapsed: 1205
BLOCKED false
BLOCKED false
TIMED_WAITING false
BLOCKED true
th3 is doing some job!
-------------------------------------------------
step: 12 , timeElapsed: 1306
BLOCKED false
BLOCKED false
TIMED_WAITING false
BLOCKED true
th3 is doing some job!
-------------------------------------------------
step: 13 , timeElapsed: 1406
BLOCKED false
BLOCKED false
TIMED_WAITING false
BLOCKED true
th3 is doing some job!
-------------------------------------------------
step: 14 , timeElapsed: 1507
BLOCKED false
BLOCKED false
TIMED_WAITING false
BLOCKED true
th3 is doing some job!
-------------------------------------------------
step: 15 , timeElapsed: 1607
BLOCKED false
BLOCKED false
TIMED_WAITING false
BLOCKED true
th3 is doing some job!
-------------------------------------------------
step: 16 , timeElapsed: 1708
BLOCKED false
BLOCKED false
TIMED_WAITING false
BLOCKED true
th3 is doing some job!
-------------------------------------------------
step: 17 , timeElapsed: 1808
BLOCKED false
BLOCKED false
TIMED_WAITING false
BLOCKED true
th3 is doing some job!
-------------------------------------------------
step: 18 , timeElapsed: 1909
BLOCKED false
TIMED_WAITING false
TERMINATED false
BLOCKED true
th2 is doing some job!
-------------------------------------------------
step: 19 , timeElapsed: 2009
BLOCKED false
TIMED_WAITING false
TERMINATED false
BLOCKED true
th2 is doing some job!
-------------------------------------------------
step: 20 , timeElapsed: 2110
BLOCKED false
TIMED_WAITING false
TERMINATED false
BLOCKED true
th2 is doing some job!
-------------------------------------------------
step: 21 , timeElapsed: 2211
BLOCKED false
TIMED_WAITING false
TERMINATED false
BLOCKED true
th2 is doing some job!
-------------------------------------------------
step: 22 , timeElapsed: 2311
BLOCKED false
TIMED_WAITING false
TERMINATED false
BLOCKED true
th2 is doing some job!
-------------------------------------------------
step: 23 , timeElapsed: 2412
BLOCKED false
TIMED_WAITING false
TERMINATED false
BLOCKED true
th2 is doing some job!
-------------------------------------------------
step: 24 , timeElapsed: 2512
BLOCKED false
TIMED_WAITING false
TERMINATED false
BLOCKED true
th2 is doing some job!
-------------------------------------------------
step: 25 , timeElapsed: 2613
BLOCKED false
TIMED_WAITING false
TERMINATED false
BLOCKED true
th2 is doing some job!
-------------------------------------------------
step: 26 , timeElapsed: 2713
BLOCKED false
TIMED_WAITING false
TERMINATED false
BLOCKED true
th2 is doing some job!
-------------------------------------------------
step: 27 , timeElapsed: 2814
BLOCKED false
TIMED_WAITING false
TERMINATED false
BLOCKED true
th2 is doing some job!
-------------------------------------------------
step: 28 , timeElapsed: 2914
BLOCKED false
TIMED_WAITING false
TERMINATED false
BLOCKED true
th2 is doing some job!
-------------------------------------------------
step: 29 , timeElapsed: 3015
BLOCKED false
TIMED_WAITING false
TERMINATED false
BLOCKED true
th2 is doing some job!
-------------------------------------------------
step: 30 , timeElapsed: 3115
BLOCKED false
TIMED_WAITING false
TERMINATED false
BLOCKED true
th2 is doing some job!
-------------------------------------------------
step: 31 , timeElapsed: 3216
BLOCKED false
TIMED_WAITING false
TERMINATED false
BLOCKED true
th2 is doing some job!
-------------------------------------------------
step: 32 , timeElapsed: 3316
BLOCKED false
TIMED_WAITING false
TERMINATED false
BLOCKED true
th2 is doing some job!
-------------------------------------------------
step: 33 , timeElapsed: 3417
TIMED_WAITING false
TERMINATED false
TERMINATED false
BLOCKED true
th1 is doing some job!
-------------------------------------------------
step: 34 , timeElapsed: 3517
TIMED_WAITING false
TERMINATED false
TERMINATED false
BLOCKED true
th1 is doing some job!
-------------------------------------------------
step: 35 , timeElapsed: 3618
TIMED_WAITING false
TERMINATED false
TERMINATED false
BLOCKED true
th1 is doing some job!
-------------------------------------------------
step: 36 , timeElapsed: 3718
TIMED_WAITING false
TERMINATED false
TERMINATED false
BLOCKED true
th1 is doing some job!
-------------------------------------------------
step: 37 , timeElapsed: 3819
TIMED_WAITING false
TERMINATED false
TERMINATED false
BLOCKED true
th1 is doing some job!
-------------------------------------------------
step: 38 , timeElapsed: 3919
TIMED_WAITING false
TERMINATED false
TERMINATED false
BLOCKED true
th1 is doing some job!
-------------------------------------------------
step: 39 , timeElapsed: 4019
TIMED_WAITING false
TERMINATED false
TERMINATED false
BLOCKED true
th1 is doing some job!
-------------------------------------------------
step: 40 , timeElapsed: 4120
TIMED_WAITING false
TERMINATED false
TERMINATED false
BLOCKED true
th1 is doing some job!
-------------------------------------------------
step: 41 , timeElapsed: 4220
TIMED_WAITING false
TERMINATED false
TERMINATED false
BLOCKED true
th1 is doing some job!
-------------------------------------------------
step: 42 , timeElapsed: 4321
TIMED_WAITING false
TERMINATED false
TERMINATED false
BLOCKED true
th1 is doing some job!
-------------------------------------------------
step: 43 , timeElapsed: 4421
TIMED_WAITING false
TERMINATED false
TERMINATED false
BLOCKED true
th1 is doing some job!
-------------------------------------------------
step: 44 , timeElapsed: 4522
TIMED_WAITING false
TERMINATED false
TERMINATED false
BLOCKED true
th1 is doing some job!
-------------------------------------------------
step: 45 , timeElapsed: 4622
TIMED_WAITING false
TERMINATED false
TERMINATED false
BLOCKED true
th1 is doing some job!
-------------------------------------------------
step: 46 , timeElapsed: 4723
TIMED_WAITING false
TERMINATED false
TERMINATED false
BLOCKED true
th1 is doing some job!
-------------------------------------------------
step: 47 , timeElapsed: 4823
TIMED_WAITING false
TERMINATED false
TERMINATED false
BLOCKED true
th1 is doing some job!
interrupted! java.lang.InterruptedException

Process finished with exit code 1
Alex
  • 3,923
  • 3
  • 25
  • 43