Why invoke Thread.currentThread.interrupt() in a catch InterruptException block?
Asked Answered
T

5

227

Why invoke the method Thread.currentThread.interrupt() in the catch block?

Transmontane answered 5/2, 2011 at 12:25 Comment(0)
A
229

This is done to keep state.

When you catch the InterruptedException and swallow it, you essentially prevent any higher-level methods/thread groups from noticing the interrupt. Which may cause problems.

By calling Thread.currentThread().interrupt(), you set the interrupt flag of the thread, so higher-level interrupt handlers will notice it and can handle it appropriately.

Java Concurrency in Practice discusses this in more detail in Chapter 7.1.3: Responding to Interruption. Its rule is:

Only code that implements a thread's interruption policy may swallow an interruption request. General-purpose task and library code should never swallow interruption requests.

Adjoining answered 5/2, 2011 at 12:28 Comment(3)
In documentation it's stated that "By convention, any method that exits by throwing an InterruptedException clears interrupt status when it does so. I think that this makes the answer clearer in terms of why you need to preserve interrupt status.Obligato
It's also worth noting that interrupt() call is the only way to set the interrupted flag once you received notification about this state through the other "delivery mechanism" - the InterruptedException and wish or cannot re-throw it.Planogamete
what do you mean by higher-level methods/thread groups?Rehm
E
81

I think this code sample makes things a bit clear. The class which does the job :

public class InterruptedSleepingRunner implements Runnable {
    @Override
    public void run() {
        doAPseudoHeavyWeightJob();
    }

    private void doAPseudoHeavyWeightJob() {
        for (int i = 0; i < Integer.MAX_VALUE; i++) {
            // You are kidding me
            System.out.println(i + " " + i * 2);
            // Let me sleep <evil grin>
            if (Thread.currentThread().isInterrupted()) {
                System.out.println("Thread interrupted\n Exiting...");
                break;
            } else {
                sleepBabySleep();
            }
        }
    }

    protected void sleepBabySleep() {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
}

The Main class:

public class InterruptedSleepingThreadMain {
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(new InterruptedSleepingRunner());
        thread.start();
        // Giving 10 seconds to finish the job.
        Thread.sleep(10000);
        // Let me interrupt
        thread.interrupt();
    }
}

Try calling interrupt without setting the status back.

Estevan answered 19/7, 2011 at 12:14 Comment(4)
so the conclusion is ??Unapproachable
Thanks. I see what you mean now: repl.it/@djangofan/InterruptedThreadExampleVetchling
I think he means that Thread.currentThread().interrupt(); allows you to exit out of thread faster, hence when InterruptedException e is caught, the thread is stopped then and there. Whereas if Thread.currentThread().interrupt(); is not used, thread keeps executing..Inset
That's not what the example depicts. If you swallow interrupt, the outside function will not exit and will continue doing sleepBabySleepVoodooism
B
23

Note:

http://download.oracle.com/javase/7/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html

How do I stop a thread that waits for long periods (e.g., for input)?

For this technique to work, it's critical that any method that catches an interrupt exception and is not prepared to deal with it immediately reasserts the exception. We say reasserts rather than rethrows, because it is not always possible to rethrow the exception. If the method that catches the InterruptedException is not declared to throw this (checked) exception, then it should "reinterrupt itself" with the following incantation:

Thread.currentThread().interrupt();

This ensures that the Thread will reraise the InterruptedException as soon as it is able.

Burleigh answered 5/2, 2011 at 12:38 Comment(0)
D
3

I would consider it a bad practice or at least a bit risky. Usually higher level methods do not perform blocking operations and they will never see InterruptedException there. If you mask it in every place you perform interruptible operation, you will never get it.

The only rationale for Thread.currentThread.interrupt() and not raising any other exception or signaling interrupt request in any other way (e.g. setting interrupted local variable variable in a thread's main loop) is the situation where you really can't do anything with the exception, like in the finally blocks.

See Péter Török's answer, if you want to better understand implications of the Thread.currentThread.interrupt() call.

Domoniquedomph answered 5/2, 2011 at 12:33 Comment(0)
P
1

Refer from java doc

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

If this thread is blocked in an I/O operation, 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.

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

So, if you change the sleepBabySleep() method in @Ajay George Answer to I/O operation or just a sysout, you don't have to set the status back to stop the program. (BTW, they don't even throw InterruptedException)

Just like @Péter Török said => This is done to keep state. (And particular for method that will throw InterruptedException)

Patiencepatient answered 20/5, 2020 at 3:23 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.